My program uses a UISplitViewController as the root view controller. In order to get the split-view to autorotate when the device orientation changes I need to subclass UISplitViewController and have it return YES in shouldAutorotateToInterfaceOrientation:
Is there a way to have the standard, ie generic UISplitViewController, autorotate? It seems silly to have to write an entire new subclass just to support orientation changes...
Thanks!
- Jake
UISplitViewController will rotate automatically as long as both of it's child view controllers return YES from -shouldAutorotateToInterfaceOrientation:.
Related
My (Universal iPhone/iPad) app will not rotate. In all of my viewcontrollers I return "YES" to the method shouldRotate, but my viewcontrollers' willRotateToInterfaceOrientation methods never get called.
Is this a common issue?
In that universal app are you using a splitViewController? If so make sure all your viewControllers return Yes to should autoRotate.
I passed an array of viewControllers (actually NavigationViewControllers) to a splitViewController and my view did not rotate. This was because my left hand viewController was not implementing shouldAutorotate. I think this is because rotation on an iPad when you use a splitViewController is different then on an iPhone. When rotated it shows two viewControllers. Both have to support landscape mode i guess?
If you do not want the rotation of the one viewController to rotate do a conditional check to see if you are on an iPad in the shouldAutoRotate method.
Are you using a tab bar? You will need to subclass your tabbar controller and return yes for should rotate.
I just ran into this. The solution was to subclass UISplitViewController and add
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
Even though the individual view controllers were already returning YES, it didn't work until I added the split view controller subclass.
My app has a view controller hierarchy set up like this:
UITabBarController
|
UINavigationController
| |
| UIViewController
|
UINavigationController
|
UIViewController
All of my view controllers that are within this hierarchy override the method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
and return YES - therefore the view controller should be able to rotate to any rotation - even upside down.
However, within this setup none of the view controllers successfully rotate. I was under the impression that navigation and tab bar controllers would rotate if their view controllers respond to rotating.
Why won't my view controllers rotate?
The only way I've been able to get them to rotate is by subclassing UINavigationController and overriding it's shouldAutorotate method, but this feels unnecessary to me and I was wondering if there's something I've missed to make this work.
Edit:
According to the User Experience Coding How-to:
If you are also using a toolbar, the view controller for each toolbar item must implement the shouldAutorotateToInterfaceOrientation: method and return YES for each of the orientations you wish to support. If you have a navigation controller for a toolbar item, the root view controller of that navigation controller must implement the shouldAutorotateToInterfaceOrientation: method and return YES.
It says 'toolbar' - but I think this is a typo and is probably supposed to be 'tab bar'.
So it seems that I'm implementing this correctly, yet my controllers still do not auto rotate.
I've run into this problem, but I can't remember the exact reason it occurred. The tab bar controller requires all of its view controllers to respond YES when asked about a particular orientation for it to rotate to that orientation.
If presented modally, it seems like it doesn't matter about the underlying VC system.
I have created a test to show this (RotationTest on GitHub), but it all seems to be working. Hopefully I can remember why I was failing with this one at some point.
Have you tried subclassing the Tabbarcontroller and setting it as your tabbarcontroller? In there, set
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
to
YES
The only way I've been able to get them to rotate is by subclassing UINavigationController and overriding it's shouldAutorotate method, but this feels unnecessary to me and I was wondering if there's something I've missed to make this work.
I don't know for sure if this is the wrong approach, but I would subclass the UITabBarController, sooner than the UINavigationController. Also, you can try wrapping everything in a subclassed UIViewController that implements the rotation method, but this will create the overhead of an extra view. I once tried to do rotation in an with UINavigationController, but it was not pretty. I suspect that the reason the views only rotate if you subclass the UINavigationController is that the view hierarchy will only pass the rotation if the parent rotates. If the parent doesn't rotate, the child won't. (Imagine an iPhone in a dock. The iPhone only can rotate if the dock rotates. Now, compare the dock to an iPhone case. The case can also rotate, so the iPhone will rotate too.)
It says 'toolbar' - but I think this is a typo and is probably supposed to be 'tab bar'.
I do not think that the HIG has a typo in that regard. The terms may interchangeable.
Generally, a "toolbar" is relevant to the view that contains it, and therefore should rotate with its parent view. A tab bar, however, is the "parent", so to speak, of the view controller on the screen. The view controller should therefore only rotate if the entire app rotates. This concept basically boils down to this: Which view (bar or view controller) is dependent on the other? (The tab bar is persistent, but the views change, or is the toolbar only there if the view is visible.)
Subclass the UITabBarController as well as the UINavigationController. It works as using xCode 4.4.
I have developed an extension that allows you to do just this without subclassing UITabBarController https://github.com/piercifani/TabBarBetterRotation
Quick problem:
I have an UITabBarController with 2 navigation controllers [lets call them Left and Right Controller]
On the default selected Left Controller I can push a new View Controller that detects interface orientation.
On the Right Controller I can push the same View Controller but it won't detect interface orientation, or for that matter, It won't even go into the shouldAutoRotateInterface method at all T___T
Haaalp!!
If it is of any relevance, the View Contoller that I'm pushing use the hidesBottomBarWhenPushed property.
Most likely this is your problem:
Tab bar controllers support a portrait
orientation by default and do not
rotate to a landscape orientation
unless all of the root view controllers support such an orientation.
When a device orientation
change occurs, the tab bar controller
queries its array of view controllers.
If any one of them does not support
the orientation, the tab bar
controller does not change its
orientation.
The solution is to override the following method on every view controller leading to your view:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
return YES;
}
For example, instead using the default UITabBarController in IB, replace it with your own subclass containing just the method above.
I'm a bit late to the party on this, but I ran into a problem with autorotation at startup for a tab bar app I wanted always to run in portrait.
The app's plist has the necessary settings to both start in and only allow portrait mode, and all my view controllers only allow portrait mode. Yet, when I started the app holding my iPhone in landscape, the app started in portrait, but then rotated to landscape!
Rather than subclass UITabBarController, I simply overrode UITabBarController's shouldAutorotateToInterfaceOrientation: method using a category on class UITabBarController. I included this code in my app delegate:
#implementation UITabBarController(UITabBarControllerCategory)
-(BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
Works beautifully, and is quite lightweight.
does your uitabbarcontroller implement the auto rotate? any child viewcontroller that wants to implement autorotate has to have its parent implement autorotate.
I have a subclass of UITabBarController which i am using so that i can rotate to use my app in landscape too.
How would i go about rotating my UI and getting each view controller to use a landscape view xib?
I have always just written apps before where returning YES for shouldAutorotate... handles it automatically for me... this isn't the case here now, as i'm using a custom view.
Thanks.
You don't need to subclass UITabBarController to get the autorotation behavior. Instead what you should do is have ALL the UIViewControllers that appear in your UITabBarController return YES for shouldAutorotateToInterfaceOrientation:. If even one of them does not, the UITabBarController will not autorotate.
As for the custom view, it is associated with a UIViewController, right? If so, then if your custom view implements layoutSubviews using the current view bounds to lay out all the subviews, then it should autorotate correctly as well.
I want to make a UISplitViewController in portrait mode just like in the Settings app. How can I do it?
A bit late, but also take a look at the MGSplitViewController by Matt Gemmel. It does what you need and so much more. It's what UISplitViewController should be, and it's a snap to implement.
From the UISplitViewController class documentation:
A split view controller supports the
same interface orientations as its
currently visible child view
controllers. Both view controllers are
displayed in landscape orientations
but only the detail view controller is
displayed in portrait orientations.
When transitioning between
orientations, the split view
controller sends messages to its
delegate object to coordinate the
display of a popover with the hidden
view controller. For more information
on the methods of this delegate
object, see
UISplitViewControllerDelegate Protocol
Reference.
(Emphesis added.)