ViewController orientation not coherent with status bar - ios

My app has this main structure: UITabBarController, where each tab hosts a UINavigationController that pushes views according to user interaction. Almost all the app is portrait orientation only, except a few specific sections.
The behavior I want is to have landscape orientation when I push one of the sections (let's say a map). In that map, the user can go back to portrait orientation. When he goes back in the main menu, he should go back to portrait orientation (landscape should not be allowed here). I don't mind if he is temporarily in landscape.
Here's some code from my UITabBarController subclass:
- (BOOL)shouldAutorotate
{
return [self.selectedViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.selectedViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
I use the same code in my UINavigationController, and in the specific menu, I have this:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotate
{
if (!UIInterfaceOrientationIsPortrait([[UIDevice currentDevice] orientation]))
return NO;
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
The behavior works almost all the time. When the orientation of the menu is landscape and the user rotates his device, he goes back to portrait, but can't go back to landscape.
My issue is: once in a while, the status bar will rotate, but not the view controller. (see picture) Each time, shouldAutorotate is called and returns the correct value (ie. it returns YES but does not autorotate).
I know this is stretching the SDK, but I'd love to make this work all the time. Any hints?

Related

Specified Orientation Not Displaying Correctly on iPad

I have a universal iOS (7.1+) app that I would like to only support portrait orientation for most views. I would like 1 view to autorotate.
The application is a navigation based application (i.e. the base view is a UINavigationViewController). In the project editor under Deployment Info I have checked portrait, landscape left and landscape right as the supported orientations.
I then restricted the autorotation of the app by implementing the -(BOOL)shouldAutorotate method and the - (NSUInteger)supportedInterfaceOrientations in my base navigation controller. As I understand it, this will restrict the orientation in any view displayed by the navigation controller.
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
The view I would like to autorotate I present modally. In the view controller that I present modally I also set -(BOOL)shouldAutorotate and - (NSUInteger)supportedInterfaceOrientations.
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrait;
}
This solution works fine on iPhone! The one modal view rotates as expected and the other views inside the However, the same view using the same code does not rotate on the iPad. I am confused as to why it works on the iPhone and not on the iPad. It seems to me that since it is the exact same view controller that it should rotate on both.

Launching app in landscape distorts entire app, when disabling landscape orientation in certain controllers

I'm utilizing a navigation controller in my app. I want all of my viewController to be in portrait only except for one, which will support landscape.
Going with an accepted answer in Stack Overflow I subclassed my nav controller and include this code:
iOS 6 - Navigation Controller Landscape Rotations For Some Views While Others Portrait Only
- (BOOL)shouldAutorotate {
id currentViewController = self.topViewController;
if ([currentViewController isKindOfClass:[IssueViewController class]])
return YES;
return NO;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
This singles out the one view controller I would like to rotate. Everything works great except when I launch the app in landscape. The image gets crushed and off centered.
screen shots here: http://imgur.com/a/jyrJ2
Any suggestions on correcting this? Thank you!
Tested your code. This works fine only when you change the orientation, but it doesn't reflect changes according to current interface orientation if you launch the app in landscape or go from one to other controller in landscape.
Use the following approach, which I have used to solve same kind of issue some time ago.
Add this code in UINavigationController subclass
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
And in you ViewController, add this code
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
//Control UIInterfaceOrientationMask here to tell which interface orientations you want to support for this ViewController
return UIInterfaceOrientationMaskPortrait;
}

How to rotate one view controller and others stay in one mode (portrait mode) in ios?

I have five view controllers and In Project Target Device Orientation I have enabled Portrait ,Landscape Left and Landscape Right. Now I want 4 view controllers out of 5 view controllers Stay in Portrait mode (Not Rotate into landscape left and landscape right) and only one view controller rotate in all modes(Portrait,landscape left,landscape right). So How can do this please tell .
Implement -(NSUInteger)supportedInterfaceOrientations for each of your ViewControllers and specify which interface orientations each controller should support.
Edit
Assuming that you have a separate implementation for each of your ViewControllers, implement -(NSUInteger)supportedInterfaceOrientations and -(BOOL)shouldAutorotate in each of your implementations.
For example
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
will ensure that your view controller supports all landscape modes. Combine this with
-(BOOL)shouldAutorotate{
return YES;
}
and your display will "flip" over when rotated.
Use the enum UIInterfaceOrientationMask to adjust which orientations are supported and try different combinations of this along with a YES/NO return value to -(BOOL)shouldAutorotate until you get the behaviour you want.
First of all, in AppDelegate, write this.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskAll;
}
Then, For UIViewControllers, in which you need only PORTRAIT mode, write these functions
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
For UIViewControllers, which require LANDSCAPE too, change masking to All.
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
//OR return UIInterfaceOrientationMaskAll;
}
Now, if you want to do some changes when Orientation changes, then use this function.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
}
NOTE Please :-
A lot depends on with which controller is your UIViewController embedded in.
Eg, If its inside UINavigationController, then you might need to subclass that UINavigationController to override orientation methods like this.
subclassed UINavigationController (the top viewcontroller of the hierarchy will take control of the orientation.) did set it as self.window.rootViewController.
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
From iOS 6, it is given that UINavigationController won't ask its UIVIewControllers for orientation support. Hence we would need to subclass it.

return back from B VIewcontroller(Fixed Portrait), to A , A is not rotating to landscape mode automatically(Device is in Landscape Mode)

I hold device in landscape mode and moved into second view controller, which only support portrait mode. when return back from second view controller(Support all orientation), First view controller is not rotating to landscape mode automatically.
if i did below code then its work in IOS6. but not working for IOS7.
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
[UIViewController attemptRotationToDeviceOrientation];
}
in IOS7 viewController is rotating but status bar is not rotating
Implement the following in VC A:
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
The solution presented by AMayes is not quite correct.
The UIViewController docs state the following:
Typically, 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 directly in decisions about what rotations are supported.
Therefore, put the following code in the UINavigationController subclass:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}

Can't lock rotation to portrait in my iOS 6.1 app

I have an app where landscape left and landscape right are both enabled in the build settings, but I'd only like these to be available in one ViewController in the app.
I'm using a navigation controller, and in the first ViewController I push onto the stack, I'd like to disable rotation altogether. I've tried all 3 of these with no success:
- (BOOL)shouldAutoRotate {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
When I rotate the device in the simulator, the layout still changes. I know the last method is deprecated in iOS 6.
Any ideas?
Fixed it. The reason was because the navigation controller was being rotated, and this was not triggering - (BOOL)shouldAutorotate to be called in the top view controller, as I thought it would.
I subclassed the navigation controller and added
- (BOOL)shouldAutorotate {
return NO;
}

Resources