How to allow for iOS status bar and iPhone X notch in Xamarin.Forms

后端 未结 3 857
心在旅途
心在旅途 2021-01-02 19:48

I\'m fairly new to this, so sorry if this is a dumb question. How do I get my Xamarin.Forms app to start below the status bar or the notch when applicable? I\'ve tried using

相关标签:
3条回答
  • 2021-01-02 20:27

    You'll need to consider the safe area but have the background colors expand to take the full screen. So you shouldn't use

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

    this will box your page with large empty spaces on the bottom and top edges.

    Instead, you should measure the safe areas and apply it as padding to your root view.

    [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 in xaml:

    <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>
    

    ref: https://xamarinhelp.com/safeareainsets-xamarin-forms-ios/ Thank Adam, not me!

    0 讨论(0)
  • 2021-01-02 20:36

    use UseSafeArea

    using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
    using Xamarin.Forms;
    
    namespace iPhoneX 
    {
        public partial class ItemsPage : ContentPage
        {
            public ItemsPage()
            {
                InitializeComponent();
    
                On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-02 20:50

    is it possible to make one thing on the screen expand all the way to the edges?

    (from this answer)

    Stretching elements out of the bounds of the safe area is arguably a use case in the case you provided. The bar is a mere background element and not content, as the navigation bar is, which also stretches to fill the whole screen.

    Having said that, you unfortunately don't get this for free, but have to implement this by yourself. Assume you have the following XAML

    <ContentPage ...>
        <StackLayout>
            <ContentView BackgroundColor="LightSkyBlue" HorizontalOptions="Fill" x:Name="Header">
                <!-- Header -->
            </ContentView>
            <ContentView x:Name="Content">
                <!-- Content -->
            </ContentView>
        </StackLayout>
    </ContentPage>
    

    In your code-behind (I would not use it like this, but to make the point it suffices. For a real application I have written a utility class, which is attached to the view and manages the insets.) you can now check for the property SafeAreaInsets being changed

    class SafeAreaPage : ContentPage
    {
        // elided constructor
    
        protected override void OnPropertyChanged(string propertyName)
        {
            if(propertyName = "SafeAreaInsets")
            {
                var insets = On<Xamarin.Forms.PlatformConfiguration.iOS>.GetSafeAreaInsets();
    
                var headerInsets = insets; // Thickness is a value type
                headerInsets.Bottom = 0;
    
                var contentInsets = insets;
                contentInsets.Top = 0;
    
                Header.Padding = headerInsets;
                Content.Padding = contentInsets;
            }
        }
    }
    

    How you set the Paddings of your views depends on your layouts, but this way you have a bit more control on how the safe area insets are used, although it is a bit fiddly.

    0 讨论(0)
提交回复
热议问题