Since the release of iPhone X, we have to deal with devices with notches and make sure our UI elements don’t overlap with the notifications bar, the notch and the task switching bar on the bottom of the screen. However, we can’t just add a fixed padding to everything to resolve this issue, because devices without notch and with smaller safe areas also exist, and we have to support them as well.

This leads to a lot of nasty spaghetti code which can be hard to maintain.

Fortunately, RedCorners.Forms comes to rescue. It provides smart alternatives to ContentPage and ContentView that can automatically adjust their paddings based on the iOS device used. Simply derive your pages from RedCorners.Forms.ContentPage2 or your views from RedCorners.Forms.ContentView2 and set their FixTopPadding and/or FixBottomPadding properties to automatically adjust their paddings based on the device.

<rf:ContentPage2
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:rf="clr-namespace:RedCorners.Forms;assembly=RedCorners.Forms"
    xmlns:vm="clr-namespace:Demos.ViewModels"
    mc:Ignorable="d"
    x:Class="Demos.Views.FixPaddingPage"
    BackgroundColor="Black"
    FixBottomPadding="{Binding FixBottomPadding}" 
    FixTopPadding="{Binding FixTopPadding}"
    UIStatusBarStyle="{Binding UIStatusBarStyle}">
    <ContentPage.BindingContext>
        <vm:FixPaddingViewModel />
    </ContentPage.BindingContext>
    <Grid BackgroundColor="White">
        <StackLayout HorizontalOptions="Fill" VerticalOptions="Center" Padding="30">
            <Grid>
                <Label Text="FixTopPadding" />
                <Switch HorizontalOptions="End" IsToggled="{Binding FixTopPadding}" />
            </Grid>
            <Grid>
                <Label Text="FixBottomPadding" />
                <Switch HorizontalOptions="End" IsToggled="{Binding FixBottomPadding}" />
            </Grid>
            <Button Text="Close" Command="{Static rf:Values.PopCommand}" />
        </StackLayout>
    </Grid>
</rf:ContentPage2>

View Model:

public class FixPaddingViewModel : BindableModel
{
    public UIStatusBarStyles UIStatusBarStyle =>
        FixTopPadding ? 
            UIStatusBarStyles.LightContent :
            UIStatusBarStyles.Default;

    bool _fixTopPadding = false;
    public bool FixTopPadding
    {
        get => _fixTopPadding;
        set
        {
            SetProperty(ref _fixTopPadding, value);
            RaisePropertyChanged(nameof(UIStatusBarStyle));
        }
    }

    bool _fixBottomPadding = false;
    public bool FixBottomPadding
    {
        get => _fixBottomPadding;
        set => SetProperty(ref _fixBottomPadding, value);
    }
}

In this example, we also change the UIStatusBarStyle to make sure it is visible for any given FixTopPadding value.