Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UINavigationController Force Rotate

My application is primarily portrait, however there is one view that REQUIRES a landscape orientation.

My views are contained within a UINavigationController, which (apparently) is the cause of this issue.

All UIViewControllers except one have this:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

The UIViewController that requires Landscape has this:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

Now, what happens is when the user reaches the landscape UIViewController, it is shown in portrait. The user can then rotate their phone and it displays in landscape as I want it to (locking to landscape). The user then progresses onwards to a portrait UIViewController and the same happens: it start in landscape, then they rotate their phone and it becomes portrait again (and locks to portrait).

It seems orientation locking is allowed between UIViewControllers, however auto-rotation / programmatically changing the orientation is somehow blocked.

How do I force the phone to update to the correct orientation?

There is a temporary solution: I can detect the orientation of the device and show a message asking them to rotate the device if it is not correct, however this is not optimal.

like image 205
Zac Altman Avatar asked Mar 22 '12 16:03

Zac Altman


3 Answers

I had the same requirement for one of my applications!!!

luckily I found a solution!

In order to keep main viewcontroller landscape, no matter from what orientation it was popped/pushed, I did the following thing: (in viewWillAppear:)

//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];

//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];

P.S.Tested on sdk 3.2.5 ios 5.0.1.

P.S. On iOS 8 previous answer results some screen flickering and also - it is not stable (In some cases It does not work for me anymore.) So, for my needs, I changed the code to: (ARC)

//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];

[self.navigationController presentViewController:[UIViewController new] animated:NO completion:^{
    dispatch_after(0, dispatch_get_main_queue(), ^{
        [self.navigationController dismissViewControllerAnimated:NO completion:nil];
    });
}];

//I added this code in viewDidDissapear on viewController class, which will be popped back.

Hopefully it will help!

like image 136
Guntis Treulands Avatar answered Oct 18 '22 04:10

Guntis Treulands


This might help. You can call the following method upon appearing, where appropriate. e.g. in -viewWillAppear:animated

attemptRotationToDeviceOrientation Attempts to rotate all windows to the orientation of the device.

+ (void)attemptRotationToDeviceOrientation

Discussion

Some view controllers may want to use app-specific conditions to determine the return value of their implementation of the shouldAutorotateToInterfaceOrientation: method. If your view controller does this, when those conditions change, your app should call this class method. The system immediately attempts to rotate to the new orientation. A rotation occurs so long as each relevant view controller returns YES in its implementation of the shouldAutorotateToInterfaceOrientation: method.

Availability

Available in iOS 5.0 and later. http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIViewController_Class/Reference/Reference.html

like image 29
Canopus Avatar answered Oct 18 '22 05:10

Canopus


Use this,

[[UIDevice currentDevice]performSelector:@selector(setOrientation:) withObject:(__bridge id)((void *)UIInterfaceOrientationLandscapeRight)];
like image 4
Thangavel Avatar answered Oct 18 '22 05:10

Thangavel