Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a consistent way to get the safe area insets for the iPhone X in Xamarin.Forms

I am currently updating some views for the iPhone X. According to this blog post it should be fairly streight-forward, but - like always - it's not as smooth as it's supposed to be.

If you are using the recommended way

public MyView()
{
    InitializeComponent();

    On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
}

the items of the View are given a Margin according to the safe area insets, but this applies to views like SearchBar, too, which already adapt to the insets out of the box. Using the code above will result in the gray background of the search bar not taking the whole width, which looks quite strange.

Fortunately the On<iOS> has an extension method SafeAreaInsets() which returns the correct insets - under certain conditions - which one for example can assign to a BindableProperty. Unfortunately the conditions under which we can obtain the insets are not very consistent.

  • When OnSizeAllocated is called the first time, SafeAreaInsets() will return 0,0,0,0
  • When the view is shown SafeAreaInsets() returns the correct value (in OnAppearing)
  • OnSizeAllocated is called multiply after rotation
    • The first time SafeAreaInsets() returns the correct value
    • The second time SafeAreaInsets() returns 0,0,0,0

My current working solution is, to override both and only set my bindable property (which is bound to my views) if the Thickness returned by SafeAreaInsets() is not default(Thickness).

I'd like to know if there is a standard way to always get the correct insets, without having to check if the insets have a sound value.

like image 748
Paul Kertscher Avatar asked Dec 05 '17 06:12

Paul Kertscher


1 Answers

I did a bit of research on this. Here's couple of my thoughts:

  1. You could actually set the UseSafeArea in XAML (docs) - that's just FYI

  2. The setting of the SafeArea happens when using this extension method, which basically sets the SafeAreaInsetsPropertyKey property and then the page Padding is updated in the UpdatePadding method. The question here is, what calls that extension method and sets it then? I checked the Xamarin.Forms github repo and the answer is simple. It gets called from the PageRenderer, when the ViewSafeAreaInsetsDidChange is called by the iOS. Which means that you don't know exactly when iOS decides to inform you about the current SafeArea - the issues that you're seeing with different values of the inset at different times.

I know it's definitely not what anyone wants but you could override the default iOS PageRenderer and hook up to the ViewSafeAreaInsetsDidChange override. Once it's called you could be 100% sure that you have current SafeArea inset value.

like image 117
Mikolaj Kieres Avatar answered Oct 21 '22 13:10

Mikolaj Kieres