在Xamarin.Forms

时间:2017-12-05 06:08:50

标签: xamarin.forms iphone-x

我目前正在为iPhone X更新一些视图。根据this blog post,它应该是相当直接的,但是 - 像往常一样 - 它不像它应该的那么顺利是

如果您使用推荐的方式

public MyView()
{
    InitializeComponent();

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

根据安全区域插入,视图的项目被赋予Margin,但这也适用于SearchBar之类的视图,它们已经适应了开箱即用的插图。使用上面的代码将导致搜索栏的灰色背景不占据整个宽度,这看起来很奇怪。

幸运的是On<iOS>有一个扩展方法SafeAreaInsets(),它返回正确的插入 - 在某些条件下 - 例如,哪一个可以分配给BindableProperty。不幸的是,我们获得内容的条件并不十分一致。

  • 第一次调用OnSizeAllocated时,SafeAreaInsets()将返回0,0,0,0
  • 显示视图时SafeAreaInsets()会返回正确的值(在OnAppearing
  • OnSizeAllocated在轮换后被称为multiply
    • 第一次SafeAreaInsets()返回正确的值
    • 第二次SafeAreaInsets()返回0,0,0,0

我目前的工作解决方案是,如果Thickness返回的SafeAreaInsets()不是default(Thickness),则覆盖两者并仅设置我的可绑定属性(绑定到我的视图)。

我想知道是否有标准方法可以始终获得正确的插入内容,而无需检查插图是否具有声音值。

2 个答案:

答案 0 :(得分:1)

我对此做了一些研究。这是我对此的几点看法:

  1. 您实际上可以在XAML(docs)中设置UseSafeArea-就是说

  2. 使用this extension method时会发生SafeArea的设置,该设置基本上是设置SafeAreaInsetsPropertyKey属性,然后页面Padding在{{1 }} 方法。这里的问题是,什么调用该扩展方法并进行设置?我检查了Xamarin.Forms github存储库,答案很简单。当ViewSafeAreaInsetsDidChange调用iOS时,将从UpdatePadding调用它。这意味着您不确切知道iOS何时决定通知您当前的PageRenderer-您在不同的时间使用不同的插图值看到的问题。

我知道这绝对不是任何人想要的,但是您可以覆盖默认的iOS SafeArea并使用PageRenderer覆盖。调用后,您可以100%确保您具有当前的ViewSafeAreaInsetsDidChange插入值。

答案 1 :(得分:0)

我使用订阅来更改属性值SafeAreaInsets。这补充了OnSizeAllocated的错误解决方案。

public bool WasAppeared { get; private set; }

public CustomContentPage() : base()
{
    if (Device.RuntimePlatform == Device.iOS)
        PropertyChanged += CustomContentPage_PropertyChanged;
}

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

    WasAppeared = true;

    SetSafeArea();
}

protected override void OnDisappearing()
{
    WasAppeared = false;

    base.OnDisappearing();
}

private void CustomContentPage_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    if (!WasAppeared)
        return;

    if (e.PropertyName == "SafeAreaInsets")
        SetSafeArea();
}

protected void SetSafeArea()
{
    if (Device.RuntimePlatform != Device.iOS)
        return;
}