繁体   English   中英

如何在 Xamarin.Forms/XLabs 中处理屏幕旋转/方向?

[英]How to handle screen rotation/orientation in Xamarin.Forms/XLabs?

我正在尝试使用此处详述的 XLabs 方法确定屏幕何时旋转(在 Android 中) How to handle screen rotation/orientation in Xamarin Forms? 我遇到了麻烦。

我覆盖了MainActivity 中OnConfigurationChanged方法

        public override void OnConfigurationChanged (Android.Content.Res.Configuration newConfig)
    {
        base.OnConfigurationChanged (newConfig);

        var xapp = Resolver.Resolve<IXFormsApp> ();
        if (xapp == null)
            return;

        switch (newConfig.Orientation) {
        case Android.Content.Res.Orientation.Landscape:
            xapp.Orientation = XLabs.Enums.Orientation.Landscape;
            break;
        case Android.Content.Res.Orientation.Portrait:
            //xapp.Orientation = XLabs.Enums.Orientation.Portrait;
            break;
        default:
            break;
        }
        }

我在使用 IXFormsApp 中的 Orientation 变量时遇到问题,即 xapp.Orientation。 XLabs 文档将其列为“受保护集”,编译器也是如此:

MainActivity.cs(109,5,109,21): error CS0200: Property or indexer 'XLabs.Platform.Mvvm.IXFormsApp.Orientation' cannot be assigned to -- it is read only

它不会自动设置(当我检查它的使用位置时,它总是设置为“无”),所以我想知道如何使用它,实际上,如何使用 XLabs/IXFormsApp 来确定回转?

在相关说明中,我还试图设置 Rotation 处理程序(不知道为什么,但我想我会试一试),结果不寻常。

            xapp.Rotation += (sender, args) =>
        {
            switch (args.Value)
            {
            case XLabs.Enums.Orientation.Landscape:
                //xapp.Orientation = XLabs.Enums.Orientation.Landscape;
                ...
                break;
            case XLabs.Enums.Orientation.Portrait:
                ...
                break;
            default:
                break;
            }
            };

如果我在 Android 代码中尝试,我会收到以下错误:

MainActivity.cs(60,4,60,22): error CS0019: Operator '+=' cannot be applied to operands of type 'System.EventHandler<XLabs.EventArgs<XLabs.Enums.Orientation>>' and 'lambda expression'

但是,如果我在 Forms 代码(使用结果的地方)中设置它,那就没问题了(尽管处理程序似乎从未真正被调用过)。 有谁知道为什么会这样?

我过去使用过两种不同的解决方案。


第一种方法是创建一个 PageBase 类,我的所有页面都继承自该类,而 PageBase 继承自常规 Page。

我的 PageBase 有两个抽象方法(所以它的孩子必须填写它),它们是 UpdateLandscape 和 UpdatePortait。 孩子们将根据页面是以横向还是纵向模式布局来填写如何布局页面的这些方法。

正如丹尼尔所说,页面有一个 OnSizeAllocated 方法。 我让 PageBase 覆盖它并让它相应地调用 UpdateLandscape 和 UpdatePortait。

如果,如您所说,您只想检查它何时旋转,那么上面的方法就可以了,因为每当您旋转手机时,都会调用 OnSizeAllocated 页面。


如果您正在检查横向与纵向,因为您希望您的代码能够随时检查,那么下面的第二个解决方案也适用。

我解决的第二种方法是使用依赖服务来填充一个 IDeviceInfo 接口,并通过检查 DeviceInfo.IsPortait() 是 true 还是 false 来编写所有动态的东西(这样我也让 DeviceInfo 有一个 Width 和 Height,所以我可以随时要求屏幕尺寸)。

在 Android 上,我填写了我的 Android 代码,如下所示:

[assembly: Dependency (typeof(Namespace.DeviceInfoProvider))]
namespace Namespace
{
  public class DeviceInfoProvider : IDeviceInfoProvider
  {
    public bool IsPortait () { return DeviceInfoManager.Width < DeviceInfoManager.Height; }
    public int GetWidth () {  return DeviceInfoManager.Width; }
    public int GetHeight () { return DeviceInfoManager.Height; }
  }

  public static class DeviceInfoManager
  {
    public static MainActivity MainActivity { get; set; }
    public static int Width { get { return MainActivity.GetWidth (); } }
    public static int Height { get { return MainActivity.GetHeight (); } }
  }
}

然后在 MainActivity 中我给了它这些方法:

public int GetWidth() {
      return (int)(Resources.DisplayMetrics.WidthPixels / Resources.DisplayMetrics.Density);
    }

    public int GetHeight() {
      return (int)(Resources.DisplayMetrics.HeightPixels / Resources.DisplayMetrics.Density);
    }

在 iOS 方面,我是这样填写的:

[assembly: Dependency (typeof(Namespace.DeviceInfoProvider))]
namespace Namespace {

  public class DeviceInfoProvider : IDeviceInfoProvider {
    public bool IsPortait() { return UIScreen.MainScreen.Bounds.Width < UIScreen.MainScreen.Bounds.Height; }

    public int GetWidth() { return (int)UIScreen.MainScreen.Bounds.Width; }

    public int GetHeight() { return (int)UIScreen.MainScreen.Bounds.Height; }
  }
}

就个人而言,我更喜欢以第二种方式编写它并检查“如果我们处于肖像模式,这里是差异”。 这样,那些在肖像和风景之间没有区别的东西只需写一次,只有不同之处才写两次。

您可以使用 OnSizeAllocated 方法覆盖来检测方向变化;

double previousWidth;
double previousHeight;

    protected override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height);

        if (previousWidth != width || previousHeight != height)
        {
            previousWidth = width;
            previousHeight = height;

            if (width > height)
            {
                // landscape mode
            }
            else
            {
                // portrait mode
            }   
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM