Rasmus Tolstrup Christensen

Orientation in Xamarin Forms

June 02, 2016 | 4 Minute Read

When my device is rotated I want the screen to rotate, but for this screen I only want to allow portrait mode? Sounds pretty simple and so it should be. When it comes to Xamarin Forms, you might run into a wall, let's break it.

Before writing this post I searched for a solution and found a lot of issues around Xamarin Forms and orientation. In the future this might be fixed but for now this is the solution I found to solve the problem.

Device orientation IOS

In one of my projects, I ran into the situation described above. Some views should be allowed to rotate while others shouldn’t. Targeting IOS, the way you allow rotation is to define it inside info.plist. Here you can define either specific allowed orientation or all, all pretty simple. infoplist But when it comes to Xamarin Forms, you can’t really define within a specific view, that you want it only in a specific orientation. Imagine you had a view with a signature control and you want Landscape orientation to be enabled, but for the rest of the application only Portrait.

The basic of orientation on IOS

When you have the allowed orientations defined inside info.plist, you can set the supported orientations of the current view by overriding GetSupportedInterfaceOrientations in AppDelegate.cs. This method returns an UIInterfaceOrientationMask where the allowed orientation(s) for a specific view can be overridden, exactly what we want to achieve.

View orientation responsibility

Before we dive deeper into the implementation of GetSupportedInterfaceOrientations, we first need a way to let each view communicate its supported orientations. To do this we introduce the ISupportOrientation interface.

public interface ISupportOrientation
{
	DeviceOrientation[] SupportedOrientation { get; }
}

public enum DeviceOrientation
{
	Undefined,
	Landscape,
	Portrait
}

A pretty simple interface, in my case I added it to the PCL, as that’s the common setup of my projects, but it should work fine with Shared projects too. Together with the interface, we also add an enum DeviceOrientation. Feel free to add additional orientations as you need them. An implementation of a view that implements ISupportOrientation might look like this.

public partial class SignatureView : ContentPage, ISupportOrientation
{
 public SignatureView()
  {
   InitializeComponent();
  }

 public DeviceOrientation[] SupportedOrientation
 {
  get
  {
   return new[] { DeviceOrientation.Landscape, DeviceOrientation.Portrait };
  }
 }
}

ISupportOrientation in action

Now that our view is ready, let’s return to AppDelegate.cs and GetSupportedInterfaceOrientations. Depending on your application, the orientation rules might change, but in this example I defined Portrait to be the default orientation.

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
 if (Xamarin.Forms.Application.Current == null || Xamarin.Forms.Application.Current.MainPage == null)
 {
  return UIInterfaceOrientationMask.Portrait;
 }

 var navigationPage = Xamarin.Forms.Application.Current.MainPage as NavigationPage;

 if(navigationPage != null)
 {
  var orientationPage = navigationPage.CurrentPage as ISupportOrientation;

  if (orientationPage != null)
  {
   UIInterfaceOrientationMask supportedMask = new UIInterfaceOrientationMask();

   foreach (var orientation in orientationPage.SupportedOrientation)
   {
    switch (orientation)
    {
     case DeviceOrientations.Portrait:
      supportedMask |= UIInterfaceOrientationMask.Portrait;
      break;
  
     case DeviceOrientations.Landscape:
      supportedMask |= UIInterfaceOrientationMask.Landscape;
	  break;

     default:
      break;
    }
   }
   return supportedMask;
  }
 }
 return UIInterfaceOrientationMask.Portrait;
}

As you can see this is a pretty simple implementation and not optimized in any special way. We check the current view for the ISupportOrientation and if multiple orientations is supported they are combined in the UIInterfaceOrientationMask.

The implementation is available as a Gist here

comments powered by Disqus