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 (I wrote a RubyMotion tutorial for Objective C developers), 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
Discussion in the ATmosphere