Wednesday 29 October 2014

IOS 8 : Restricting orientation on a View Controller

In my recent xamarin project (iOS 8 app) one of the requirement was to restrict the orientation at ViewController level. There had been lot of changes from the apple side related to screen orientation.
  • In iOS 4, it was possible to force app rotation when changing view controllers in a tab bar controller and a navigation controller, as well as when presenting/dismissing a controller.
  • Then in iOS 6 it became impossible to force app rotation except when presenting/dismissing a view controller.
  • Now, in iOS 8, it is impossible to force app rotation at all (except at launch). It can prefer a certain orientation, so that once it is in that orientation it will stay there, but it cannot force the app to go into that orientation.
    Instead, your view controller is expected to "adapt". There are several WWDC 2014 videos concentrating on "adaptation", and now I'm starting to understand that this is one reason why this is so important.
Workaround to restrict the orietation
Xamarin:

Step 1:
In info.plist unselect all the orientation as shown in the image below:




Step 2:
In AppDelegate.cs:

Define a boolean type variable to assign the value of each ViewController Orientation type.

public partial class AppDelegate : ApplicationDelegate
{
public bool RestrictRotation {
            get;
            set ;
     }
}
        }
  
also add the function bellow to get the supported orientation type at run time.

Export ("application:supportedInterfaceOrientationsForWindow:")]
public UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, IntPtr forWindow)
{
     if (this.RestrictRotation)
         return UIInterfaceOrientationMask.Portrait;
     else
         return UIInterfaceOrientationMask.All;
}
  

Step 3:

In ViewController add the following code:

a) For Portrait view:

i) Inside ViewDidLoad:
The following code will return true to the AppDelegate -> GetSupportedInterfaceOrientations. This will enable to get the UIInterfaceOrienntationMask to Portrait.

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    this.RestrictRotation(true);
  

ii) Add the functions below to the View Controller.

public override bool ShouldAutorotate()
{
     return false;
}

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations ()
{
     return UIInterfaceOrientationMask.Portrait;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation ()
{
      return UIInterfaceOrientation.Portrait;
}

void RestrictRotation(bool restriction)
{
AppDelegate app =(AppDelegate)UIApplication.SharedApplication.Delegate;
            app.RestrictRotation = restriction;
}
  

b) For Landscape and Portrait view:
i) Inside ViewDidLoad:
The following code will return true to the AppDelegate -> GetSupportedInterfaceOrientations. This will enable to get the UIInterfaceOrienntationMask to Portrait and Landscape.

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    this.RestrictRotation(false);
  

ii) Add the functions below to the View Controller.

public override bool ShouldAutorotate()
{
     return false;
}

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations ()
{
     return UIInterfaceOrientationMask.Portrait;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation ()
{
      return UIInterfaceOrientation.Portrait;
}

void RestrictRotation(bool restriction)
{
AppDelegate app =(AppDelegate)UIApplication.SharedApplication.Delegate;
            app.RestrictRotation = restriction;
}
  

Image:

View 1:

Portrait Only:




View 2:

Portrait and Landscape:



Please pick up the code example from github...

Enjoy coding!!!