如何在 Xamarin.Forms 中设置 ContentPage 方向

How to set ContentPage orientation in Xamarin.Forms

我正在使用 Xamarin.Forms 创建一个跨平台应用程序,我所有的 ContentPages 都位于 PCL.

我正在寻找一种方法来将单个 ContentPageorientation 设置并锁定为 Landscape,最好不必在每个 activity 中创建另一个 activity特定于平台的项目。

由于我的 ContentPage.Content 设置为 ScrollView,我尝试将 ScrollOrientation 设置为 Horizontal,但这没有用。

我也试过使用 RelativeLayout,但我看不到 Orientation 属性。

public class PlanningBoardView : ContentPage //Container Class.
    {
        public PlanningBoardView()
        {
            scroller = new ScrollView ();

            Board = new PlanningBoard();

            scroller.Orientation = ScrollOrientation.Horizontal;
            scroller.WidthRequest = Board.BoardWidth;
            scroller.Content = Board;

            Content = scroller;
        }
    }

我尝试的最后一件事是使用 Xamarin Studio 的 Intellisense 版本和 Xamarin Forms API Doc's 查看我可用的不同布局,none 其中有一个 Orientation 属性.

我担心唯一的方法是创建第二个平台特定的 Activity 只为这个平台 ContentPage 并将方向设置为横向。

虽然这种方法可行,但它使屏幕之间的导航变得更加复杂。

目前正在 Android 中进行测试。

不想这么说,但这只能使用 custom renderers 或特定于平台的代码

在android中可以设置MainActivity的RequestedOrientation属性为ScreenOrientation.Landscape.

在 iOS 中,当 Xamarin.Forms.Application.Current.MainPage 是您感兴趣的ContentPage



Android

[assembly: Xamarin.Forms.ExportRenderer(typeof(MyCustomContentPage), typeof(CustomContentPageRenderer))]

public class CustomContentPageRenderer : Xamarin.Forms.Platform.Android.PageRenderer
{
    private ScreenOrientation _previousOrientation = ScreenOrientation.Unspecified;

    protected override void OnWindowVisibilityChanged(ViewStates visibility)
    {
        base.OnWindowVisibilityChanged(visibility);

        var activity = (Activity)Context;

        if (visibility == ViewStates.Gone)
        {
            // Revert to previous orientation
            activity.RequestedOrientation = _previousOrientation == ScreenOrientation.Unspecified ? ScreenOrientation.Portrait : _previousOrientation;
        }
        else if (visibility == ViewStates.Visible)
        {
            if (_previousOrientation == ScreenOrientation.Unspecified)
            {
                _previousOrientation = activity.RequestedOrientation;
            }

            activity.RequestedOrientation = ScreenOrientation.Landscape;
        }
    }
}

iOS

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
    public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
    {
        if (Xamarin.Forms.Application.Current == null || Xamarin.Forms.Application.Current.MainPage == null)
        {
            return UIInterfaceOrientationMask.Portrait;
        }

        var mainPage = Xamarin.Forms.Application.Current.MainPage;

        if (mainPage is MyCustomContentPage ||
           (mainPage is NavigationPage && ((NavigationPage)mainPage).CurrentPage is MyCustomContentPage) ||
           (mainPage.Navigation != null && mainPage.Navigation.ModalStack.LastOrDefault() is MyCustomContentPage))
        {
            return UIInterfaceOrientationMask.Landscape;
        }

        return UIInterfaceOrientationMask.Portrait;
    }
}

Dealdiane 的代码对我来说效果很好,稍作改动:

protected override void OnWindowVisibilityChanged(ViewStates visibility) {
    base.OnWindowVisibilityChanged( visibility );

    IRotationLock page = Element as IRotationLock;
    if ( page == null )
        return;

    var activity = (Activity) Context;

    if ( visibility == ViewStates.Gone ) {
        // Revert to previous orientation
        activity.RequestedOrientation = _previousOrientation;
    } else if ( visibility == ViewStates.Visible ) {
        if ( _previousOrientation == ScreenOrientation.Unspecified ) {
            _previousOrientation = activity.RequestedOrientation;
        }

        switch ( page.AllowRotation() ) {
            case RotationLock.Landscape:
                activity.RequestedOrientation = ScreenOrientation.SensorLandscape;
                break;
            case RotationLock.Portrait:
                activity.RequestedOrientation = ScreenOrientation.SensorPortrait;
                break;
        }
    }
}

这也可以通过使用 MessagingCenter class 将消息从 Form 项目发送到宿主项目来完成。不使用自定义渲染器或依赖服务如下,

public partial class ThirdPage : ContentPage
  {
      protected override void OnAppearing()
      { 
          base.OnAppearing(); 
         MessagingCenter.Send(this, "allowLandScapePortrait");
      }
       //during page close setting back to portrait
      protected override void OnDisappearing()
      {
          base.OnDisappearing(); 
          MessagingCenter.Send(this, "preventLandScape");
      }
  }

更改 mainactivity 以接收消息并设置 RequestedOrientation

[Activity(Label = "Main", ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,ScreenOrientation = ScreenOrientation.Portrait)]
 public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
  {        
  //allowing the device to change the screen orientation based on the rotation
  MessagingCenter.Subscribe<ThirdPage>(this, "allowLandScapePortrait", sender =>
  { 
   RequestedOrientation = ScreenOrientation.Unspecified;
  });
 //during page close setting back to portrait
 MessagingCenter.Subscribe<ThirdPage>(this, "preventLandScape", sender =>
  { 
   RequestedOrientation = ScreenOrientation.Portrait;
  });
 }

在我的博客中查看更多内容 post : http://www.appliedcodelog.com/2017/05/force-landscape-or-portrait-for-single.html

如果您也 运行 遇到 Android 设备轮换 returns 的问题,您返回提示输入用户电子邮件,您可以跟进 ADAL 和 MSAL 的修复进度这里:

https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/issues/1622 https://github.com/xamarin/xamarin-android/issues/3326