How to Handle Different Orientations in Ios

How to handle different orientations in iOS

Using -[UIDevice setOrientation:] is a private API, and will get your application rejected. See this question.

What you ask is not possible using public API and is also not recommended from HIG standpoint. What is supported and you should implement, is modal presentation of the different view controllers with different supported interface orientation. This is why the default implementation of UINavigationController is to always rotate; it assumes all view controllers have the same supported interface orientations.

Take for example video playback on iPhone. Open the video apps (that comes with iOS). The root view controller only supports portrait orientation. However, start a video, and a modal view controller pops up which only supports landscape interface orientations. This seems exactly the behavior you wish to achieve.

This is why preferredInterfaceOrientationForPresentation is not called. preferredInterfaceOrientationForPresentation only gets called when using presentViewController:animated:.

A small gotcha, if you require a navigation bar in each stage of your scene, you will need to enclose each modal view controller with a navigation controller. You can then pass the required data in prepareForSegue: by accessing topViewController of the navigation controller object in the segue.


Here is an example project which behaves correctly according to your requirements (or at least will give you ideas how to implement):

http://www.mediafire.com/?zw3qesn8w4v66hy

What is the right way to handle orientation changes in iOS 8?

Apple recommends using size classes as a coarse measure of how much screen space is available, so that your UI can significantly change its layout and appearance. Consider that an iPad in portrait has the same size classes as it does in landscape (Regular width, Regular height). This means that your UI should be more or less similar between the two orientations.

However, the change from portrait to landscape in an iPad is significant enough that you may need to make some smaller adjustments to the UI, even though the size classes have not changed. Since the interface orientation related methods on UIViewController have been deprecated, Apple now recommends implementing the following new method in UIViewController as a replacement:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id )coordinator
{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

// Code here will execute before the rotation begins.
// Equivalent to placing it in the deprecated method -[willRotateToInterfaceOrientation:duration:]

[coordinator animateAlongsideTransition:^(id context) {

// Place code here to perform animations during the rotation.
// You can pass nil or leave this block empty if not necessary.

} completion:^(id context) {

// Code here will execute after the rotation has finished.
// Equivalent to placing it in the deprecated method -[didRotateFromInterfaceOrientation:]

}];
}

Great! Now you're getting callbacks right before the rotation starts, and after it finishes. But what about actually knowing whether the rotation is to portrait or to landscape?

Apple recommends thinking about rotation as simply a change in size of the parent view. In other words, during an iPad rotation from portrait to landscape, you can think of it as the root-level view simply changing its bounds.size from {768, 1024} to {1024, 768}. Knowing this then, you should use the size passed into the viewWillTransitionToSize:withTransitionCoordinator: method above to figure out whether you are rotating to portrait or landscape.

If you want an even more seamless way to migrate legacy code to the new iOS 8 way of doing things, consider using this simple category on UIView, which can be used to determine whether a view is "portrait" or "landscape" based on its size.

To recap:

  1. You should use size classes to determine when to show fundamentally different UIs (e.g. an "iPhone-like" UI vs. an "iPad-like" UI)
  2. If you need to make smaller adjustments to your UI when size classes don't change but your container (parent view) size does, such as when an iPad rotates, use the viewWillTransitionToSize:withTransitionCoordinator: callback in UIViewController.
  3. Every view in your app should only make layout decisions based on the space that it has been given to layout in. Let the natural hierarchy of views cascade this information down.
  4. Similarly, don't use the statusBarOrientation -- which is basically a device-level property -- to determine whether to layout a view for "portrait" vs "landscape". The status bar orientation should only be used by code dealing with things like UIWindow which actually live at the very root level of the app.

iOS - different screen orientations for different view controllers

Ok, just in case this interests anyone, this was my solution, using the accepted answer here:

The thing I was missing was in my approach - The landscape VC can't be under the same root VC as the portrait ones, it needs to be or have its own root VC, which is in landscape.

So first, I separated the landscape VC from the rest in the storyboard, now it's completely independent. Next, I created a "view controller switch" method, which basically loads a new controller, sets it to be the root controller, and releases the previous root controller:

+(void)loadController:(UIViewController *)VControllerToLoad andRelease:(UIViewController *)VControllerToRelease
{
//adjust the frame of the new controller
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect windowFrame = [[UIScreen mainScreen] bounds];
CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
VControllerToLoad.view.frame = firstViewFrame;
//set the new controller as the root controller
[[[UIApplication sharedApplication].delegate window] setRootViewController:VControllerToLoad];
//kill the previous view controller
[VControllerToRelease.view removeFromSuperview];
}

In the landscape VC I added this code:

-(BOOL)shouldAutorotate
{
return YES;
}

And whenever I need to present the landscape VC or go back the the portrait VCs, I just use the VC switch method. For example:

[AppUtils loadController:landscapeViewController andRelease:portraitNavigationController];

That's it! Now everything works like a charm! :)

How to Handle Orientation in IOS Objective C only for one screen and reset when press

Add below code inside viewWillAppear on all viewControllers you want to show portrait only. don't forget to mark Device Orientation to both Portrait and Landscape modes.

NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];

The best way to handle different orientations in an iPad

You can implement two views in one xib and change which is visible in rotation, but this results in requiring twice as many IBOutlets one for each property for each view.

If it is difficult layout changes I would probably change the xib, but for simple stuff (where the autosizing resizing isn't working great) I often just set the frame to the new position in code. Keep in mind this create a nice chunk of code that is not ro pretty to look at. I will often mock the view up in IB still so I can get the frame positions to move to.

Different orientation for iPhone and iPad in one storyboard

Open your info.plist file as code and paste this code:

UISupportedInterfaceOrientations

UIInterfaceOrientationPortrait

UISupportedInterfaceOrientations~ipad

UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight

Works well for me!

Different layouts in portrait and landscape mode

Note - the answers here are good and do address the problem, but on older versions of iOS.

For iOS11 (Xcode 9) you should consider Adaptive Layouts as referenced here:
https://www.raywenderlich.com/162311/adaptive-layout-tutorial-ios-11-getting-started



Related Topics



Leave a reply



Submit