Supporting Different Orientations Within an iOS App
I’ve seen people asking how to support different device orientations within the same iOS app, especially since iOS 6 introduced some changes to how device orientation is handled and with the growing popularity of RubyMotion, there is a new breed of developers. It’s really straightforward when the entire app supports the same set of orientation(s). But it gets a little confusing when you want different screens to support different orientations.
Here’s some sample code for how to do it correctly in RubyMotion. Developers using Objective C should be able to adapt this too.
In Rakefile (for ObjC developers, do something similar in your info.plist file), set the following to indicate all the orientations supported by the app. If you have a screen in your app that plays video and you want to allow the user to also play it in landscape, you need to include both portrait and landscape orientations here even if the rest of the app is always in portrait.
app.interface_orientations =
[:portrait, :landscape_left, :landscape_right]
The rest of it is code. If you use UINavigationControllers anywhere in your app, you will want to use your own subclass instead:
class AppDelegate
def application(application,
didFinishLaunchingWithOptions:launchOptions)
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
@window.rootViewController =
NavigationController.alloc.initWithRootViewController(
PortraitViewController.alloc.init)
@window.makeKeyAndVisible
true
end
end
The custom UINavigationController just forwards the relevant calls to it’s topmost view controller:
class NavigationController < UINavigationController
#####Orientation
def shouldAutorotate
topViewController.shouldAutorotate
end
def supportedInterfaceOrientations
topViewController.supportedInterfaceOrientations
end
def preferredInterfaceOrientationForPresentation
topViewController.preferredInterfaceOrientationForPresentation
end
def shouldAutorotateToInterfaceOrientation(interfaceOrientation) {
topViewController.shouldAutorotateToInterfaceOrientation(
interfaceOrientation)
end
end
Here’s how to implement a UIViewController subclass that only supports portrait orientation:
class PortraitViewController < UIViewController
def initWithNibName(nibName, bundle:nibBundle)
super(nibName, nibBundle)
self.view.backgroundColor = UIColor.blueColor
b = UIButton.buttonWithType(UIButtonTypeRoundedRect)
b.frame = [[60, 100], [200, 20]]
b.setTitle('Show VC that rotates', forState:UIControlStateNormal)
b.addTarget(self, action:'click',
forControlEvents:UIControlEventTouchUpInside)
view.addSubview(b)
self
end
def click
vc = PortraitAndLandscapeViewController.new
navigationController.pushViewController(vc, animated:true)
end
#####Orientation
def shouldAutorotate
true
end
def supportedInterfaceOrientations
UIInterfaceOrientationMaskPortrait
end
def shouldAutorotateToInterfaceOrientation(interfaceOrientation)
interfaceOrientation == UIInterfaceOrientationPortrait
end
#Optional depending on your app
def preferredInterfaceOrientationForPresentation
UIInterfaceOrientationPortrait
end
end
Here’s how to implement a UIViewController subclass that supports both portrait and landscape orientations:
class PortraitAndLandscapeViewController < UIViewController
def initWithNibName(nibName, bundle:nibBundle)
super(nibName, nibBundle)
self.view.backgroundColor = UIColor.greenColor
self
end
#####Orientation
def shouldAutorotate
true
end
def supportedInterfaceOrientations
UIInterfaceOrientationMaskAllButUpsideDown
end
def shouldAutorotateToInterfaceOrientation(interfaceOrientation)
interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight
end
#Optional depending on your app
def preferredInterfaceOrientationForPresentation
UIInterfaceOrientationPortrait
end
end