Why Can't I Force Landscape Orientation When Use Uinavigationcontroller

Why can't I force landscape orientation when use UINavigationController?

Best way to do this is the create extend UINavigationController and write your orientation function inside the extended class.

Class Declaration:

@interface MyNavigationControllerViewController : UINavigationController

@property(nonatomic, assign) UIInterfaceOrientation orientation;
@property(nonatomic, assign) NSUInteger supportedInterfaceOrientatoin;
@end

Implementation of MyNavigationController

@implementation MyNavigationController

@synthesize supportedInterfaceOrientatoin = _supportedInterfaceOrientatoin;

@synthesize orientation = _orientation;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
_supportedInterfaceOrientatoin = UIInterfaceOrientationMaskLandscape;
_orientation = UIInterfaceOrientationLandscapeLeft;
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)shouldAutorotate
{
return YES;
}

-(NSUInteger)supportedInterfaceOrientations

{
return _supportedInterfaceOrientatoin;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return self.orientation;
}

@end

and use your extended like MyNavigationController as navigation controller to your rootviewcontroller.

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;
@property (strong, nonatomic) MyNavigationControllerViewController *myNavController;

- (void) reloadAppDelegateRootViewControllerLandscape;
- (void) reloadAppDelegateRootViewController;
@end

So your application delegate didfinishlounchingwithoptions code will be as follow.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];

self.myNavController = [[MyNavigationController alloc] initWithRootViewController:self.viewController];
[self.myNavController setNavigationBarHidden:YES];
self.window.rootViewController = self.myNavController;

[self.window makeKeyAndVisible];
return YES;
}

Only way you can provide different orientation for two different view with same navigation controller isto reload the navigation controller itself. So if you add two methods

- (void) reloadAppDelegateRootViewController{
[[[UIApplication sharedApplication].delegate window] setRootViewController:nil];
[(MyNavigationControllerViewController *)self.myNavController setOrientation:UIInterfaceOrientationPortrait];
[(MyNavigationControllerViewController *)self.myNavController setSupportedInterfaceOrientatoin:UIInterfaceOrientationMaskAll];
[[[UIApplication sharedApplication].delegate window] setRootViewController:self.myNavController];
}

- (void) reloadAppDelegateRootViewControllerLandscape{
[[[UIApplication sharedApplication].delegate window] setRootViewController:nil];
[(MyNavigationControllerViewController *)self.myNavController setOrientation:UIInterfaceOrientationLandscapeLeft];
[(MyNavigationControllerViewController *)self.myNavController setSupportedInterfaceOrientatoin:UIInterfaceOrientationMaskLandscape];
[[[UIApplication sharedApplication].delegate window] setRootViewController:self.myNavController];
}

and call these function after pushing and pop views.

Note:- I don't know whether it is a good way or bad way.

How to force set Landscape Orientation with UINavigationController (Swift 2.0 iOS 9)

If this is something you really want to do, subclass UINavigationController then add this code:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .Landscape
}

Trying to force an orientation imperatively is unwise; it's better to tell iOS what you want (as above) then let it calculate the orientation as best it can.

Force change UINavigationController orientation

override func viewDidLoad() {
super.viewDidLoad()
let value = UIInterfaceOrientation.landscape.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscape
}

override var shouldAutorotate: Bool {
return true
}

UINavigationController Force Rotate

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!

Transitioning to landscape rotation within a uinavigationcontroller

What appears in YouTube app when transitioning from the movie info screen to the actual movie is not navigation interface - it's a modal view. This always works reliably: if you show a view modally (using presentModalViewController) and it can appear in only one orientation, the app rotates to that orientation.

So, the solution is, don't push your landscape view into the navigation controller; present it as a modal view.

Okay, but perhaps you want to fool the user into believing that we are still in the navigation interface? Then give the modal view a navigation interface configured to look like the main navigation interface! So when you present the modal view, it will appear to the user as if the navigation interface has rotated (though there will not be a rotation animation).

Now, the only problem is that the navigation interface in the modal view has no Back button if we are looking at its root view. This breaks the illusion (and makes it hard for the user to come back). The solution to that is a trick: push the landscape view twice into the navigation interface before presenting it as a modal view. That way, what is showing in the navigation interface is the second view on the stack, and so there is a Back button. Then, in the navigation controller delegate, catch the Back button and dismiss the modal view when the user tries to return to what you know to be the root level. So:

- (void) doButton: (id) sender { // appear to navigate into a landscape view
SecondViewController* sec = [[SecondViewController alloc] init];
sec.title = self.title; // to give the correct Back button title
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:sec];
SecondViewController* sec2 = [[SecondViewController alloc] init];
[nav pushViewController:sec2 animated:NO];
[self presentModalViewController:nav animated:YES];
nav.delegate = self; // so that we know when the user navigates back
}

// and here's the delegate method
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
if (viewController == [navigationController.viewControllers objectAtIndex:0])
[self dismissModalViewControllerAnimated:YES];
}

UINavigationController and autorotation

I was about to tell you that there was probably no way, but then I had a thought. It would be difficult to get right, but you might be able to make it work if you used two separate UINavigationControllers: one that controls the root view and prohibits rotation, and one for the child views that allows it. You would manually handle the transition to and from the root controller and the child controller.

You'd have to patch up the child navigation controller to have the correct back button. And, of course, you'd have to handle the back button press yourself. You would probably have to use a dummy UINavigationBar to do the animation from one navigation controller to the next so that the transition will look right. You would also have to animate the "push" transition between the navigation controllers, as well, which might take a bit of tweaking to get it to look right. You would have to:

  1. Configure a dummy navigation bar to exactly match the outgoing navigation controller's and place it directly on top of the navigation controller's bar. (You could copy the configuration of the current view controller's UINavigationItem and push it on)
  2. Place the new navigation controller off-screen at the right edge
  3. Animate the movement of the new and old controllers' frames from right to left
  4. Create a copy of the UINavigationItem for the incoming view controller and push it on the dummy navigation bar
  5. When the animation completes, remove the dummy UINavigationBar from the view, and also the outgoing navigation controller.

All of this is a lot of work, but if you're very clever (and very tenacious), you might be able to get it to work. I'd love to see the result!

That said, you might be better off just using setOrientation: and taking your chances with the App Store approval process ;-)

Force UIViewController to only show in landscape mode

I'm sorry but this answer will be very short: If you're using the UINavigationController, you can't. The answer @jer gives is therefore incorrect. The Apple documentation states:

All child view controllers in your UITabBarController or UINavigationController do not agree on a common orientation set.

I recently had this question answered on a bounty and my app rejected in the process. Read up on that here: How to constrain autorotation to a single orientation for some views, while allowing all orientations on others?

The only solution you have, is to throw away the UINavigationController and rewrite it with something of your own.



Related Topics



Leave a reply



Submit