Force Landscape View on one UIViewController only - ios

I have an app that is portait mode only. I only have one View Controller that I need to force into landscape mode (A customer signature view) so there is more room for the customer to sign.
How can I force one ViewController to appear in landscape mode. Leaving the rest in portrait?
I have tried setting the app's General Deployment info to Portrait, Landscape Left
And then using this code on the Signature View
- (BOOL)shouldAutorotate {
return YES;
}
and returning NO on all other view controllers. But that didn't seem to work.
I also included
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
Is this possible?

Try this code in the Signature View Controller
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeLeft] forKey:#"orientation"];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:#"orientation"];
}

You're just missing the following code below, if your UIViewController is a rootcontroller of a navigationcontroller you need to put the code in the navigationcontroller. Hope this helps, good luck.
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}

Following is the the way its working for me:-
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
and
- (BOOL)shouldAutorotate {
return NO;
}
Another way is to define orientation in prepareForSegue and fixed orientation of the required VC and set shouldAutorotate to NO in that VC.
Let me know if mentioned code doesn't work for you.

Related

How to force view to enter landscape in iOS?

I've see a dozen of possible related questions on SO, but no one seems duplicated:
how to force view to rotate to landscape in viewdidload?
force landscape ios 7
IOS - How to force the view to landscape
Force landscape for one view controller ios
iOS - Force Landscape Orientation
How to make app fully working correctly for autorotation in iOS 6?
My app is a tab-based application.
Currently when entering certain views, I can rotate my phone to landscape to let my view enter landscape.
Main Code:
// In app delegate
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
if (_allowRotation == YES) {
return UIInterfaceOrientationMaskLandscape;
}
else {
return UIInterfaceOrientationMaskPortrait;
}
}
In views that I want to be landscape, I set allowRotation to YES.
But I want to force views to enter landscape.
In other word, when entering certain views, it automatically enters landscape, no need to rotate phone. Even user locks the screen as portrait. How to achieve this?
I'm using iOS 10.
You have to override the onDidLoad or onDidAppear of the specific view that you want to move it to landscape, for example i added it to viewWillAppear and Disappear:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
self.navigationController.navigationBarHidden = NO;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
-(void)viewWillDisappear:(BOOL)animated {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
[super viewWillDisappear:animated];
}
so we the view appear the application move to landscape and when the move disappear it come again to portrait. and for the appDelegate you have to add this:
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
if ([navigationController.viewControllers.lastObject isKindOfClass:[OpencvViewController class]])
{
return UIInterfaceOrientationMaskLandscape;
}
else
return UIInterfaceOrientationMaskPortrait;
}
Call [UIViewController attemptRotationToDeviceOrientation] when you need rotate orientation
Yours code will be something like that:
appDelegate.allowRotation = YES;
[UIViewController attemptRotationToDeviceOrientation];
Use below code in the specific view controller that you want to rotate in to landscape mode.
-(void)viewDidLayoutSubviews
{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
You need to use
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
for container view controller in window.rootViewController hierarchy or while presenting view controller over another one.
This enforces you controller to appear in landscape orientation.
The simplest example is assigning rootViewController to the main window.
If you use UIInterfaceOrientationMaskLandscape in your view controller it appears in landscape from the very beginning.
If you try to pack your controller into navigation controller you'll need to subclass the latter to define UIInterfaceOrientationMaskLandscape in it because it is the container for your own view controller.
The same is valid for other containers (e.g. tabBarController or your own containers) which have parent-child link.
While presenting view controller you have also another method to fix orientation:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation

Make view controller rotate immediately base on device orientation

I have 2 view controllers A and B. View controller A is portrait only and view controller B can rotate.
When the phone is landscape, I push view controller A and it's orientation is portrait -> good.
But when i push view controller B from view controller A (the phone is still landscape), view controller B's orientation is portrait, that is not what i want.
I have to rotate device to portrait then landscape to make view controller B rotate to landscape.
My question is, how can i make view controller B rotate immediately after push from A, in respect to device orientation?
Use this it may be resolve your poblem
AppDelegate.m
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskLandscape;
}
ViewController
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
To rotate device orientation use this code in your viewWillAppear and viewWillDisAppear according to need
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
And to rotate View use this code
[self shouldAutorotate];
[self supportedInterfaceOrientations];
And Define this method in ViewController.m
-(BOOL)shouldAutorotate{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
It will Help.Thankyou

Maintaining orientation of parent view after modal view has been presented with different orientation

So I am developing an iPad app that supports only landscape mode except for on one modal view controller. The issue I am having is that once I present the modal view and change the orientation to portrait then dismiss the view, the parent view (which should only support landscape) is in portrait mode until I rotate the device in which it then goes back to landscape and stays that way. I have been beating myself up trying to figure out how to keep the parents view original orientation but haven't been able to find a solution.
I have the following code in my app delegate to allow orientation changes on only that single modal view (GalleryPhotoViewer) :
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
//Support Portrait mode only on Photoviewer
if ([[presentedViewController presentedViewController] isKindOfClass:GalleryPhotoViewController.class] ) {
orientations = UIInterfaceOrientationMaskAll;
}else{
orientations = [presentedViewController supportedInterfaceOrientations];
}
}
return orientations;
}
From the parent class (PhotosViewController) I am calling :
GalleryPhotoViewController *gpView = [GalleryPhotoViewController new];
[self presentViewController:gpView animated:YES completion:nil];
Also in my parent (and other views) I have the following code to disallow portrait mode :
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(interfaceOrientation == UIInterfaceOrientationPortrait) {
return YES;
} else {
return NO;
}
}
Any ideas on how I can keep the orientation on my parent view? I was thinking about possibly just programmatically changing the orientation on the parent in the viewWillAppear method once the modal is dismissed but then I wouldn't know what the previous orientation was, not to mention I haven't been able to find code to do this regardless for ios6.
EDIT/SOLUTION : So I found a solution and what I ended up doing was leaving the application:supportedInterfaceOrientationsForWindow: code and just adding the UINavigation subclass to the parent view that was presenting the modal view and everything worked as expected and the parent retained its original orientation while the modal was able to change freely.
In my parent :
//To make sure that this view remains in Landscape
#implementation UINavigationController (Rotation_IOS6)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
#end
Thanks #matt for the suggestions.
I think the problem is your use of application:supportedInterfaceOrientationsForWindow:. Instead, get rid of that, and start with a UINavigationController subclass and make that the class of the root view controller that is your navigation interface. Then:
In the UINavigationController subclass, return UIInterfaceOrientationMaskLandscape from supportedInterfaceOrientations.
In the presented (modal) view controller, return UIInterfaceOrientationMaskAll from supportedInterfaceOrientations.

iOS 6: How do I restrict some views to portrait and allow others to rotate?

I have an iPhone app that uses a UINavigationController to present a drill-down interface: First one view, then another, up to four levels deep. I want the first three views restricted to portrait orientation and only the last view should be allowed to rotate to landscape. When returning from the fourth view to the third and the fourth view was in landscape orientation I want everything to rotate back to portrait.
In iOS 5 I simply defined shouldAutorotateToInterfaceOrientation: in each of my view controllers to return YES for the allowable orientations. Everything worked as described above, including the return to portrait even if the device was being held in landscape orientation when returning from view controller #4 to #3.
In iOS 6 all view controllers rotate to landscape, breaking those that weren't meant to. The iOS 6 release notes say
More responsibility is moving to the app and the app delegate. Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. [...] The system asks the top-most full-screen view controller (typically the root view controller) for its supported interface orientations whenever the device rotates or whenever a view controller is presented with the full-screen modal presentation style. Moreover, the supported orientations are retrieved only if this view controller returns YES from its shouldAutorotate method. [...] The system determines whether an orientation is supported by intersecting the value returned by the app’s supportedInterfaceOrientationsForWindow: method with the value returned by the supportedInterfaceOrientations method of the top-most full-screen controller.
So I subclassed UINavigationController, gave my MainNavigationController a boolean property landscapeOK and used this to return the allowable orientations in supportedInterfaceOrientations. Then in each of my view controllers' viewWillAppear: methods I have a line like this
[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
to tell my MainNavigationController the desired behavior.
Here comes the question: If I now navigate to my fourth view in portrait mode and turn the phone over it rotates to landscape. Now I press the back button to return to my third view which is supposed to work portrait only. But it doesn't rotate back. How do I make it do that?
I tried
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]
in the viewWillAppear method of my third view controller, but it doesn't do anything. Is this the wrong method to call or maybe the wrong place to call it or should I be implementing the whole thing in a totally different way?
I had the same problem and found a solution that works for me.
To make it work, it is not sufficient to implement - (NSUInteger)supportedInterfaceOrientations in your UINavigationController.
You also need to implement this method in your controller #3, which is the first one to be portrait-only after popping controller #4.
So, I have the following code in my UINavigationController:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
if (self.isLandscapeOK) {
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}
In view controller #3, add the following:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
You don't need to add anything to your view controllers #1, #2, and #4.
This works for me, I hope it will help you.
Add a CustomNavigationController
Override these methods in it:
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
Now add all orientations in the plist
In the view controller add only the required ones:
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
these methods override the navigation controller methods
After looking through every answer in countless similar questions on SO, none of the answers worked for me, but they did give me some ideas. Here's how I ended up solving the problem:
First, make sure your Supported Interface Orientations in your project's target contain all orientations that you want for your rotating view.
Next, make a category of UINavigationController (since Apple says not to subclass it):
#implementation UINavigationController (iOS6AutorotationFix)
-(BOOL)shouldAutorotate {
return [self.topViewController shouldAutorotate];
}
#end
Import that category and the view controller that you want to be able to rotate (which I'll call RotatingViewController) to your highest level view controller, which should contain your navigation controller. In that view controller, implement shouldAutorotate as follows. Note that this should not be the same view controller that you want to rotate.
-(BOOL)shouldAutorotate {
BOOL shouldRotate = NO;
if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
shouldRotate = [navigationController.topViewController shouldAutorotate];
}
return shouldRotate;
}
Finally, in your RotatingViewController, implement shouldAutorotate and supportedInterfaceOrientations as follows:
-(BOOL)shouldAutorotate {
// Preparations to rotate view go here
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}
The reason you need to do this is because iOS 6 gives control of rotation to the root view controller instead of the top view controlller. If you want an individual view's rotation to behave differently than other views in the stack, you need to write a specific case for it in the root view controller.
I don't have enough reputation to comment on #Brian's answer so I'll add my note here.
Brian mentioned that iOS6 gives the rotation control to the rootViewController - this could not only be a UINavigationController as mentioned but also a UITabBarController, which it was for me. My structure looks like this:
UITabBarController
UINavigationController
UIViewControllers ...
UINavigationController
UIViewControllers ...
So I added the methods first in a custom UITabBarController, then in a custom UINavigationController and then lastly in the specific UIViewController.
Example from the UITabBarController and UINavigationController:
- (BOOL)shouldAutorotate {
return [self.viewControllers.lastObject shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.viewControllers.lastObject supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}
I'd like to give a partial answer to my own question. I found the following line of code, used in the viewWillAppear method of my third UIViewController, to work:
[[UIDevice currentDevice]
performSelector:NSSelectorFromString(#"setOrientation:")
withObject:(id)UIInterfaceOrientationPortrait];
But I don't really like this solution. It is using a trick to assign to a read-only property which according to Apple documentation represents the physical orientation of the device. It's like telling the iPhone to jump to the correct orientation in the hand of the user.
I am very tempted to leave this in my app since it simply works. But it doesn't feel right so I'd like to leave the question open for a clean solution.
This is I am using for orientation support in ios 6.0
-(BOOL)shouldAutorotate{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
Being that this is a highly viewed thread. I thought I would add what I believe is the easiest answer. This works for ios8 and up
-(BOOL)shouldAutorotate
{
return YES;
}
and
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
That's it. Enjoy!
Oh, and my ViewControllers are embedded in a navigation controller, which I did not need to subclass or configure in any way.
This might not work for everyone, but it works great for me. Instead of implementing...
[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
in viewWillAppear in all of my controllers, I decided to centralize this process inside of my UINavigationController subclass by overriding the UINavigationControllerDelegate method navigationController:willShowViewController:animated:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
self.previousVCLandscapeOK = self.isLandscapeOK; // Store the current VC's orientation preference before pushing on the new VC so we can set this again from within the custom "back" method
self.isLandscapeOK = NO; // Set NO as default for all VC's
if ([viewController isKindOfClass:[YourViewController class]]) {
self.isLandscapeOK = YES;
}
}
I have found that this delegate method doesn't get called when popping a VC off of the nav stack. This wasn't an issue for me because I am handling the back functionality from within my UINavigationController subclass so that I can set the proper navigation bar buttons and actions for specific VC's like this...
if ([viewController isKindOfClass:[ShareViewController class]]) {
UIButton* backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 57, 30)];
[backButton setImage:[UIImage imageNamed:#"back-arrow"] forState:UIControlStateNormal];
[backButton addTarget:self action:#selector(back) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem* backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
viewController.navigationItem.leftBarButtonItem = backButtonItem;
UIImageView* shareTitle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"share-title"]];
[shareTitle setContentMode:UIViewContentModeScaleAspectFit];
[shareTitle setFrame:CGRectMake(0, 0, shareTitle.frame.size.width - 10, shareTitle.frame.size.height - 10)];
viewController.navigationItem.titleView = shareTitle;
} else if(...) {
...
}
Here is what my back method looks like to handle popping the VC off of the stack and to set the appropriate rotation preference...
- (void)back {
self.isLandscapeOK = self.previousVCLandscapeOK;
self.previousVCLandscapeOK = NO;
[self popViewControllerAnimated:YES];
}
So, as you can see, basically all that is happening is I'm first setting me two properties...
#property (nonatomic) BOOL isLandscapeOK;
#property (nonatomic) BOOL previousVCLandscapeOK;
in navigationController:willShowViewController:animated: which will determine what the supported orientations are within that VC that is about to be presented. When popping a VC, my custom "back" method is being called and I'm then setting the isLandscapeOK to what was stored via the previousVCLandscapeOK value.
As I said, this might not work for everyone, but it works great for me and I don't have to worry about adding code to each of my view controllers, I was able to keep it all centralized in the UINavigationController subclass.
Hope this helps someone as it did me.
Thanks, Jeremy.
Go to you Info.plist file and make the change
You want to Force iOS 6 app portrait only then you can add to a UIViewController subclass below methods
- (BOOL)shouldAutorotate {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return YES;
} else {
return NO;
}
}
- (NSUInteger)supportedInterfaceOrientations {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return UIInterfaceOrientationMaskAll;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
I wanted to have all my VCs locked to portrait orientation except one. This is what worked for me.
Add support for all orientations in the plist file.
In the root view controller, detect the kind of view controller thats on top of the window and set the orientation of the app accordingly in the supportedInterfaceOrientations method. For example, I needed my app to rotate only when the webview was on top of the stack. Here's what I added in my rootVC :
-(NSUInteger)supportedInterfaceOrientations
{
UIViewController *topMostViewController = [[Utils getAppDelegate] appNavigationController].topViewController;
if ([topMostViewController isKindOfClass:[SVWebViewController class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
return UIInterfaceOrientationMaskPortrait;
}
I don't have enough reputation to answer #Ram S question under #micmdk reply so I'll add my note here.
When you use UITabbarController, try to change self.viewControllers.lastObject in
#micmdk's code to self.selectedViewController like this:
- (BOOL)shouldAutorotate {
return [self.selectedViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations {
return [self.selectedViewController supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return [self.selectedViewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
You can implement and override shouldAutorotate() and supportedInterfaceOrientations var in all of your View Controller classes that should be presented in a different orientations than ones defined in PLIST of your app.
However, in a nontrivial User Interface you might face a problem to add it in dozens of classes and you do not want to make all of them subclass of several common that supports it (MyBaseTableViewController, MyBaseNavigationController and MyBaseTabBarController).
Since you cannot override those method/var on UIViewController directly, you may do that on its subclasses that are typically base classes of yours like UITableViewController, UINavigationController and UITabBarController.
So you may implement a few extensions and still setup MyPreciousViewController to show in a different orientations than all others like this Swift 4 code snippet:
extension UITableViewController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let last = self.navigationController?.childViewControllers.last,
last != self {
return last.supportedInterfaceOrientations
} else {
return [.portrait]
}
}
}
extension MyPreciousViewController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait,.landscape]
}
}
extension UINavigationController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait]
}
}
extension UITabBarController {
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return [.portrait]
}
}
I've solved the same kind of issue.
If you are using the UINavigationController to push the view controllers, you have to set the methods below.
extension UINavigationController{
override open var shouldAutorotate: Bool {
if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
{
return true
}
return false
}
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
{
return .portrait
}
return .landscapeRight
}
override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
{
return .portrait
}
return .landscapeRight
}
}
In place of LoginViewController use which UIViewController you want show. In my case, I want to show the LoginViewController in the Portrait mode other ViewControllers in landscape mode.
Please use the following method to solve this issue
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
return only the orientation you want!!!

How do I force a specific UIInterfaceOrientation on an individual view in a UINavigationController?

Okay, so here's the situation:
I have an app in which I only want ONE specific view in a UINavigationController to have a landscape orientation. This view is a UIImageView that I'm capturing a signature on (THAT part works awesome). So, like this:
previous view --> signature view --> next view
(portrait) (landscape) (portrait)
I can't seem to find a good way to force the device orientation to landscape on that signature screen. It'll never make sense to have a portrait orientation on the signature view because there's really not adequate room for signing in that screen width.
So, any bright ideas on how to accomplish this? I've considered possibly doing the signature view modally, thus breaking out of the navigation controller. Thoughts?
You can try to force Device to rotate to necessary orientation - but you need to handle it manually (in addition to overriding UIViewController orientation handling methods).
To rotate device you can use next methods:
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
But in it may not work in all situations...
Also available undocumented approach:
[[UIDevice currentDevice] performSelector:NSSelectorFromString(#"setOrientation:")
withObject:(__bridge id)((void*)UIInterfaceOrientationLandscapeLeft)];
Just override this UIViewController method to only return true for landscape like so and the iphone will be forced to rotate to that device orientation, since it has no other option.
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
Unfortunately, all root UIViewControllers inside of a Navigation Controller must support any of their child orientations. This means that the first view controller in your setup must support landscape, otherwise the child will only support portrait.
The best way to implement what you are looking for is to create a UIViewController that displays its content view on a rotated transform, and just default all UIViewControllers in that stack to portrait.
I think you can embed this view inside a view controller and overwrite the ShouldRotateToInterfaceOrientation method.
Good luck!
To use a View in only landscape, I have the following in the ViewController:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
This might be what your looking for.
// Rotates the view.
CGAffineTransform transform = CGAffineTransformMakeRotation(3.14159/2);
self.view.transform = transform;
// Repositions and resizes the view.
CGRect contentRect = CGRectMake(-80, 80, 480, 320);
self.view.bounds = contentRect;
from http://www.iphonedevsdk.com/forum/iphone-sdk-development/1394-landscape-uiviewcontroller-uiview-rotation.html
I have an app that has landscape only views that even starts in landscape. This was working fine in iOS 5.x but stopped working in iOS 6.x
After trying many many things, some more questionable than others, I found a solution that to me is clear and predictable.
I did several things.
-- I kept the views in landscape mode in IB.
-- I checked both landscape modes in the project settings - there a four icons there to control it
-- Orientation mgmt has changed in iOS 6.x. I had to overwrite a few methods to support changing to landscape
this method is for iOS 5.x
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations.
return (interfaceOrientation & UIInterfaceOrientationMaskLandscape);
}
these 2 methods are for iOS 6.x
- (NSUInteger)supportedInterfaceOrientations
{
NSUInteger supportedOrientations = UIInterfaceOrientationMaskLandscape;
return supportedOrientations;
}
- (BOOL)shouldAutorotate
{
return YES;
}
-- But the key was to change the logic in the AppDelegate. Original code I had there was adding a subview (controller.view) to the window. This stopped working in iOS 6.x - I changed the call to window.setRootController. That was the final step that sealed it - it would not work without making this final change
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//[self.window addSubview:viewController.view];
[self.window setRootViewController:viewController];
[self.window makeKeyAndVisible];
return YES;
}
The UINavigationController overrides the contain UIViewController orientation settings, so you have to create a custom subclass of UINavigationController with the following for 5.1:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ([[self topViewController] isKindOfClass:[SigCaptureViewController class]]) {
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
} else {
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
}
For 6.0 and above you need:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
if ([[self topViewController] isKindOfClass:[EXTRASigCaptureViewController class]]) {
return UIInterfaceOrientationMaskLandscape;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
What I haven't figured out is how to make the force the UINavigationController to rotate. calling [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO] causes the status bar to rotate but doesn't cause the view to rotate.

Resources