Home » Android » android – How to set ContentPage orientation in Xamarin.Forms

android – How to set ContentPage orientation in Xamarin.Forms

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’m using Xamarin.Forms to create a cross platform application, all of my ContentPages are situated within the PCL.

I’m looking for a way to set and lock the orientation of a single ContentPage to Landscape, preferably without having to create another activity in each of the platform specific projects.

Since my ContentPage.Content is set to a ScrollView, I’ve tried setting the ScrollOrientation to Horizontal, however this did not work.

I’ve also tried using a RelativeLayout, but I can’t see an Orientation property on this.

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

The last thing I tried was using Xamarin Studio’s version of Intellisense and the Xamarin Forms API Doc’s to look through the different Layouts available to me, none of which had a Orientation property.

I fear the only way to do this is by creating a second platform specific Activity just for this one ContentPage and setting the orientation to landscape.

Although this method would work, it makes the Navigation between screens a lot more complex.

This is currently being tested in Android.

How to&Answers:

Hate to say this but this can only be done using custom renderers or a platform-specific code

In android, you can set the RequestedOrientation property of the MainActivity to ScreenOrientation.Landscape.

In iOS, you can override GetSupportedInterfaceOrientations in the AppDelegate class to return one of the UIInterfaceOrientationMask values when Xamarin.Forms.Application.Current.MainPage is the ContentPage that you are intereted in.

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

Answer:

This can also be done by sending the message from Form project to host project using MessagingCenter class. without using the custom renderer or dependency service as follows,

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");
      }
  }

Change in mainactivity to receive the message and set 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;
  });
 }

Check for more in my blog post : http://www.appliedcodelog.com/2017/05/force-landscape-or-portrait-for-single.html

Answer:

If you are also running into issue on Android where device rotation returns you back to prompt for user email, you can follow up progress of fixes for both ADAL and MSAL here:

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

Answer:

Dealdiane’s code works well for me with minor change:

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