I am making a navigation based app and I need only portrait orientation except in a ZoomPictureViewController ( Zoom in, zoom out images) that supports all orientations.
I am presenting ZoomPictureViewController and returning YES in shouldAutorotateToInterfaceOrientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
But I get no rotation. I know that shouldAutorotateToInterfaceOrientation, willRotateToInterfaceOrientation, RotateToInterfaceOrientation are only get called on the current/visible view controller but this is not happening in my case. I have checked it via putting breakpoints and NSLog.
Are you using any type of Navigation Controller or a Tab View Controller? I've noticed that there are issues when rotating a UIView that's not the first or only view as a direct child of the main window.
So if your UIView is part of a Navigation Controller or a Tab View Controller, you'll also need to override shouldAutoRotateToInterfaceOrientation on the Navigation Controller or Tab View Controller.
Also I here's an important gotcha in the Apple documentation that might explain the problem you are having.
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.
Related
I'm trying to work with the iOS6 Auto-rotation mess.
I've looked at almost every single SO question relating to it, and no matter what I try, I can't get rotation working how I need it.
The app is using storyboards, and the layout is as follows:
Navigation controller ---> Root view controller ---> Tab view controller ---> View controller ---> Landscape view controller.
The view controller auto-rotates when I rotate the simulator, but when segueing back to the previous view (that is set to portrait), the view becomes landscape, when it should be portrait. If I rotate the simulator back, the view auto-rotates to portrait again, but this should've been done automatically!
I've implemented (UIInterfaceOrientation)preferredInterfaceOrientationForPresentationand it doesn't get called in any view controller I put it in.
I've subclassed the NavigationController to return the topViewController's shouldAutoRotate, supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation and auto-rotation when rotating the simulator seems to work, but preferredInterfaceOrientationForPresentation never does its job.
Does anyone have a solution to this?
It would appear Apple have removed the ability to push a view in a specific orientation. preferredInterfaceOrientationForPresentation does get called, but only when popping back or presenting a view controller. I had to present my landscape view rather than push it, and set shouldAutoRotate = NO.
Refer to: In iOS6, trouble forcing ViewController to certain interfaceOrientation when pushed on stack for more details.
I have an application that plays videos via a MPMoviePlayerViewController that's presented after a selection action performed on a UITableViewController, which is embedded in a UINavigationController which is embedded in a UITabBarController.
TabBar Controller > Navigation Controller > Table View Controller * MPMoviePlayerViewController
Everything works as expected in iOS5, but upgrading to iOS6 I found that the video did not rotate as expected after being presented. If I selected more supported interface orientations on the target summary page, it causes the whole application to rotate.
The Apple documentation says the following in the UIViewController class reference:
In iOS 6, your app supports the interface orientations defined in your
app’s Info.plist file. A view controller can override the
supportedInterfaceOrientations method to limit the list of supported
orientations. Generally, the system calls this method only on the root
view controller of the window or a view controller presented to fill
the entire screen; child view controllers use the portion of the
window provided for them by their parent view controller and no longer
participate in directly in decisions about what rotations are
supported. The intersection of the app’s orientation mask and the view
controller’s orientation mask is used to determine which orientations
a view controller can be rotated into.
But I'm not sure when the child view controllers are actually participating in the rotation decision. Will I need to change the way my Tab Bar Controller responds to shouldAutorotate and supportedInterfaceOrientations when a movie is playing?
The basic answer is that the rotation behavior of all View Controllers is determined by the "top most" view controller, but the MPMoviePlayerViewController determines its own rotation behavior since it acts as a "view controller presented to fill the entire screen".
For example: if I had a single-view application, the auto-rotate methods would be handled on the view controller for the single view. If I embed that view in a tab bar, then the tab bar controller implementation would handle those messages. If I embed the view in a navigation bar inside a tab bar, the tab bar implementation would still be the one handling the messages (it's still the "root view controller" if the other view controllers are embedded inside it).
MPMoviePlayerViewController will respond YES to shouldAutorotate and will support landscape orientations. It is still possible to prevent the movie from rotating (by not having portrait orientations selected on the target summary page), but the settings you choose for your view controller hierarchy will not affect its ability to do so. When the MPMoviePlayerViewController is presented, it is the view controller handling the autorotate messages. When it is not presented, the Tab Bar Controller is in charge.
I have an app with a mainwindow which contains a tabbar controller and a number of different views. I want the whole thing to be able to rotate in each direction, however doing
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
didn't help, while that did work in other apps.
The UITabBarController requires that you enable rotation on all view controllers it manages. So each view controller should return YES for that method for the orientations you wish to rotate to.
If you wanted each view to rotate, you have to return YES on each view in the tab bar controller as well.
I have a Navigation Controller and TabBar. I would like to know how the iPod app handles allowing only the play screen to rotate. I have tried to replicate this on iOS 4.2, and if that one screen rotates to landscape and you navigate back, the old screen is too. This is undesired... is there anyway to make the 2nd screen in rotate while not causing the rest of the screens or any of the TabBars view controllers elsewhere do so?
Thanks.
Make sure your rotatable view returns YES in shouldAutorotateToInterfaceOrientation: method of UIViewController.
Make sure your non rotatable view returns NO in shouldAutorotateToInterfaceOrientation: method of UIViewController.
Subclass UITabBarController, override shouldAutorotateToInterfaceOrientation: and handle rotation here based on current UIViewController's shouldAutorotateToInterfaceOrientation: return value. You have to also check if current view controller is UINavigationController or not and if yes, you have to get current view controller from UINavigationController too.
It's not recommended to do this (I mean subclassing of UITabBarController), but UITabBarController forbids rotation if not all UIViewControllers do allow rotation.
You need to state that in the 2nd screen the device orientation is only the desired screen orientation. So for every controller you create you need to implement shouldautorotatetointerfaceorientation:.
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.