SafeAreaInsets For Xamarin.Forms In iOS

Starting with the iPhoneX, is a notch at the top of the screen. The page of you iOS application always starts from the very top of the screen, and up until now, you could just set the top padding to 20, to ensure you move down below the status bar. The iPhoneX has a notch that is larger than 20px, and you now need to account for this in your app designs.

No Padding View

Here is how an iPhone 8 and iPhone X look, with no padding at all.

Top Padding

Here is how your app with a 20px padding, on an iPhone8 vs iPhoneX, will look. You can see here this fails to clear the status bar, on an iPhoneX, and hence we now need to account for this new notch.

UseSafeArea

If you are just putting padding at the top of your page, then starting in Xamarin.Forms 2.5.0, you can use a Platform Specific property. Just place this in your ContentPage XAML.

xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core" 
ios:Page.UseSafeArea="true"

Now your layout will look like this.

Padding Content

But now lets move into the real world, where a lot of apps actually like starting from the top, and pad their content, not the page. We want to color the status bar and move our content down. But, using the SafeAreaInsets we get this.

Not exactly the desired effect.

Using Effects

In order to counter this, we need to go down to the native platform and manually apply these insets.

Note: I have only accounted for portrait orientations here. More work may need to be done if you also support landscape.

Below is the SafeAreaPaddingEffect. If it has a top notch, it applies the inset padding. If not, it applies a default 20px padding.

[assembly: ResolutionGroupName("Enterprise")]
[assembly: ExportEffect(typeof(SafeAreaPaddingEffect), nameof(SafeAreaPaddingEffect))]
namespace Enterprise.iOS.Effects
{
    class SafeAreaPaddingEffect : PlatformEffect
    {
        Thickness _padding;
        protected override void OnAttached()
        {
            if (Element is Layout element)
            {
                if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
                {
                    _padding = element.Padding;
                    var insets = UIApplication.SharedApplication.Windows[0].SafeAreaInsets; // Can't use KeyWindow this early
                    if (insets.Top > 0) // We have a notch
                    {
                        element.Padding = new Thickness(_padding.Left + insets.Left, _padding.Top + insets.Top, _padding.Right + insets.Right, _padding.Bottom);
                        return;
                    }
                }
                // Uses a default Padding of 20. Could use an property to modify if you wanted.
                element.Padding = new Thickness(_padding.Left, _padding.Top + 20, _padding.Right, _padding.Bottom);
            }
        }

        protected override void OnDetached()
        {
            if (Element is Layout element)
            {
                element.Padding = _padding;
            }
        }
    }
}

Then we can apply the effect to the element we actually want the padding to occur on.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"                 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="Enterprise.View.Features.Authentication.LoginView"                 
             xmlns:effect="clr-namespace:Enterprise.View.Effects">        
    <Grid>                      
        <Grid.RowDefinitions>               
            <RowDefinition Height="100"/>                
            <RowDefinition Height="*" />            
        </Grid.RowDefinitions>            
        <ContentView BackgroundColor="Green">                
            <ContentView.Effects>                    
                <effect:SafeAreaPaddingEffect />                
            </ContentView.Effects>                
            <Label Text="Hello, from XamarinHelp.com" />            
        </ContentView>                    
    </Grid>
</ContentPage>

This finally gives us the desired padding.



XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,200+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts