Xamarin.Forms 和 iOS:如何将 UseSafeArea 和背景图像结合起来?

Gol*_*ike 2 iphone background-image ios xamarin.forms safearealayoutguide

我有一个关于iOS安全区域使用的问题。

我通过 a使用背景图像,并在此背景图像上RelativeLayout显示一个表单。margin在表单的容器上使用了 iOS 版本:效果很好,但iPhone X上的渲染效果不太好。

<RelativeLayout>

    <Image Source="background.jpg" Opacity="0.75"
           Aspect="AspectFill"
           RelativeLayout.WidthConstraint =
               "{ConstraintExpression Type=RelativeToParent, Property=Width}"
           RelativeLayout.HeightConstraint =
               "{ConstraintExpression Type=RelativeToParent, Property=Height}" />

    <ScrollView RelativeLayout.WidthConstraint =
                    "{ConstraintExpression Type=RelativeToParent, Property=Width}"
                 RelativeLayout.HeightConstraint =
                    "{ConstraintExpression Type=RelativeToParent, Property=Height}">    
    <ScrollView.Margin>                
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
        </OnPlatform>
    </ScrollView.Margin>

    <StackLayout>
        <!-- Header -->
        <StackLayout VerticalOptions="Start">
            <fnc:HunterHeader />
        </StackLayout>

        <!-- Form -->
        <StackLayout VerticalOptions="CenterAndExpand"
                     Spacing="6" Margin="20">
            <!-- ... -->
        </StackLayout>
    </StackLayout>
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

所以我尝试将 设为UseSafeAreatrue 但我得到了顶部和底部边距。

是否可以解决此问题并将 UseSafeArea 和背景图像结合起来?或者有没有办法只为 iPhone X 添加特定的边距?

gan*_*way 6

选项 1 - 将安全区域应用于特定控件而不是页面

安全区域可以设置在特定控件上,而不是整个页面上。例如,安全区域值可以设置为 的边距或填充ScrollView。还需要考虑方向变化(如果您的应用程序支持)。

XAML

<RelativeLayout>

    <Image Aspect="AspectFill" Source="background.png" 
           RelativeLayout.WidthConstraint = "{ConstraintExpression Type=RelativeToParent, Property=Width}"
           RelativeLayout.HeightConstraint = "{ConstraintExpression Type=RelativeToParent, Property=Height}"  />

    <ScrollView x:Name="scrollView"
                RelativeLayout.WidthConstraint = "{ConstraintExpression Type=RelativeToParent, Property=Width}"
                RelativeLayout.HeightConstraint = "{ConstraintExpression Type=RelativeToParent, Property=Height}">    

        <StackLayout Margin="20, 0" Spacing="20">

            <!-- Header -->
            <StackLayout>
                <BoxView BackgroundColor="Black" HeightRequest="50" />
            </StackLayout>

            <!-- Form -->
            <StackLayout Spacing="20">
                <BoxView BackgroundColor="White" HeightRequest="150" />
                <BoxView BackgroundColor="White" HeightRequest="150" />
                <BoxView BackgroundColor="White" HeightRequest="150" />
                <BoxView BackgroundColor="White" HeightRequest="150" />
                <BoxView BackgroundColor="White" HeightRequest="150" />
                <BoxView BackgroundColor="White" HeightRequest="150" />
            </StackLayout>

        </StackLayout>

    </ScrollView>

</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

代码隐藏

    private double width = 0;
    private double height = 0;
    private bool safeAreaSetInitially;

    protected override void OnAppearing()
    {
        base.OnAppearing();

        if (!this.safeAreaSetInitially)
        {
            this.SetSafeAreaOnContentContainer();
            this.safeAreaSetInitially = true;
        }
    }

    protected override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height); //must be called

        if (Math.Abs(this.width - width) > double.Epsilon || Math.Abs(this.height - height) > double.Epsilon)
        {
            this.width = width;
            this.height = height;

            if (this.width > this.height)
            {
                // reconfigure for landscape if needed
            }
            else
            {
                // reconfigure for portrait if needed
            }

            // reset safe area on rotation as the landscape/portrait safe areas are different
            this.SetSafeAreaOnContentContainer();
        }
    }

    private void SetSafeAreaOnContentContainer()
    {
        if (Device.RuntimePlatform == Device.iOS)
        {
            // set safe insets on content that you want to be within the safe area
            var safeInsets = On<Xamarin.Forms.PlatformConfiguration.iOS>().SafeAreaInsets();
            safeInsets.Top += 20; // add any other custom design margin specific to iOS (the extra 20 came from the original XAML)
            this.scrollView.Margin = safeInsets;
        }
    }
Run Code Online (Sandbox Code Playgroud)

结果

在此输入图像描述

选项 2 - 使用Page.BackgroundImage属性

根据需求,另一种选择是仅使用BackgroundImage的属性Page(它不受On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true)方法的影响)。这种方法的一个问题是,BackgroundImage 在 iOS 中是“平铺的”。要解决此问题,请创建一个Xamarin.Forms.ContentPage不会“平铺” BackgroundImage 的自定义渲染器。这是一个例子