簡體   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