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



我试图确定当屏幕旋转(在Android中)使用这里详细的XLabs方法如何处理Xamarin窗体中的屏幕旋转/方向?我用起来有点麻烦。

我在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的方向变量有麻烦,即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

并且它不会自动设置(当我检查它在哪里使用时,它总是设置为'None'),所以我想知道如何利用它,事实上,如何使用XLabs/IXFormsApp来确定旋转?

在一个相关的说明,我也试图设置旋转处理程序(不知道为什么,但我想我会给它一个不寻常的结果)。

            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继承一个普通的页面。

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

Pages有一个OnSizeAllocated方法,如Daniel所说。我让PageBase覆盖它,并使它调用UpdateLandscape和UpdatePortait相应。

如果,正如你所说,你只是想检查它什么时候旋转,上面的工作很好,当你旋转你的手机时,OnSizeAllocated会被调用一个页面。


如果你正在检查横向和纵向,因为你希望你的代码能够随时检查,那么下面的第二个解决方案也可以工作。

我解决它的第二种方法是使用依赖服务来填充一个IDeviceInfo接口,并通过检查DeviceInfo. isportait()是否为真或假来编写所有动态的东西(这种方式我也让DeviceInfo有一个宽度和高度,所以我可以在任何时候请求屏幕尺寸)。

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

最新更新