iOS UIInterfaceOrientation - ios

My iOS app supports both landscape and portrait. The splash screen, login view and the home view are all portrait.
Now if I rotate the device to landscape and start the app all three views are and stay in portrait which is what is needed. But if I start the app in portrait and during splash screen I rotate the device to landscape the login screen is shown in landscape then automatically moves to portrait. Same for home screen (auto login, when user has already logged in and reopened the app, it goes directly to home screen).
I used this
[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIInterfaceOrientationPortrait] forKey:#"orientation"];
in viewDidLoad, viewDidAppear, viewWillAppear and viewWillDisappear. I also used
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
So, what I want to achieve is to keep the views in portrait even if I rotate the device during the splash screen.
Thank you.

Try putting this in your viewDidLoad call:
// Change to portrait if in landscape mode
if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
And remember to call super in supportedInterfaceOrientations
-(NSUInteger)supportedInterfaceOrientations{
[super supportedInterfaceOrientations];
return UIInterfaceOrientationMaskPortrait;
}
Hope that helps.

You should override your viewController's shouldAutorotate method and return there NO in those controllers, which you don't want to rotate.
EDIT: Try comment-out the shouldAutorotate method and implement
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}

There was a problem with the flow of the app that was causing the problem. The solutions provided by Ryan and Soberman are helpful. These lines of code should work fine
supportedInterfaceOrientations
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];

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

iOS: Limit screen orientation

I have an app which has a rootViewController and several child views. I want to lock the screen orientation to portrait for all of the views except one. The one view is an UIPageViewController which display's several web views and it needs to be landscape.
I can force it into landscape mode with the following code in my viewDidLoad:
NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
I can't seem to prevent the view from transitioning back to portrait on rotation. I need to lock it into landscape mode.
The following code does not seem to prevent rotation:
- (BOOL)shouldAutorotate {
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskLandscape);
}
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationLandscapeLeft;
}
I'm targeting 7.1 and up. What am I missing?

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

Lock child UIViewController to Portrait only in iOS 8

I have a Navigation Controller that contains a Parent UIViewController that supports all orientation. I want my Parent UIViewController to present its Child UIViewController that only supports Portrait orientation only. How can this be done in iOS 8?
I tried settings the supportedInterfaceOrientations to return UIInterfaceOrientationMaskPortrait only for my Child UIViewController, but it's not working.
A simple way to do that is:
In your child View Controller you can define this delegate method:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
add this line at the begin of your ViewDidLoad method:
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
This is a simple solution to force orientation in Portrait mode.
According to update provided it seems that there is a proper answer at
Support landscape for only one view in UINavigationController

iPad UISplitViewController Launch Orientation - Root View Displayed In Portrait

So I have a UISplitViewController that is the root view of my program. I have set the initial orientation to be LandscapeLeft and have all 4 orientations supported in my plist.
If I launch the app in portrait - the view that is shown is my root view not the detail view which obviously is not what I want. As soons as I rotate the device, everything works from there.
I have scoured this site and others but have found no fixes. The closest I have come is the adding the following to my app delegate:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
if (UIDeviceOrientationIsValidInterfaceOrientation([UIDevice currentDevice].orientation)) {
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft;
else
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
}
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
So this essentially forces it to draw correctly, which works great except for when the app launches with the device laying flat. Then I dont know the portrait vs landscape (and I know of no way to find it). So I basically then cant accurately say what to do.
The larger thing is this above code is a HACK, and there should be a better way, but for the life of me I cant find it.
Any ideas?
Thanks for your code on fixing this for portrait and landscape. I found a quick fix for the issue when its flat on the desk or upside down(not sure who would start the app upside down, but the same issue happens in this case):
if (UIDeviceOrientationIsValidInterfaceOrientation([UIDevice currentDevice].orientation)) {
if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft;
else if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
}
else {
if (([UIApplication sharedApplication].statusBarOrientation == 1) || ([UIApplication sharedApplication].statusBarOrientation == 0))
{
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationPortrait;
}
else {
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeLeft;
}
NSLog(#"orientation: %d", [UIApplication sharedApplication].statusBarOrientation);
}
In my App, this works because I just wanted to force them into portrait to start and if they move to landscape after that, it rotates and works fine because I support all orientations.
I don't think this will work in all cases, but this might help you get on the right track. You just need to play with the statusBarOrientation value and manually set it based on what you find works if the InterfaceOrientation is not valid(which it isn't if the device is flat on a table or upside down).
Hope that helps...
Edit: Also, I have a need in my App for knowing orientation while they are picking new items in the SplitViewController, so it was being wonky when the device was flat or upside down. And the way I detected if it was flat or upside down was to first see if the orientation was valid like you did:
if (UIDeviceOrientationIsValidInterfaceOrientation([UIDevice currentDevice].orientation))
But then if its not, I check to see if self.popoverController is nil. If its not, then its in portrait and if it is, then its landscape (based on how the splitViewController works by setting that to nil or not):
if (self.popoverController)
{
NSLog(#"in portrait");
}
else {
NSLog(#"in landscape");
}
This wouldn't work in the App Delegate while the App is launching though because this detailViewController isn't being used at that point. Just thought I'd let you know if it helps out any.
Your RootViewController is showing in place of your detailViewCOntroller?
it seems you're doing something bad... (maybe inverted viewControllers order in SplitViewController.viewControllers ?)
You need to make sure to add your UISplitViewController's view to the UIWindow INSIDE the application:application didFinishLaunchingWithOptions: method of your app delegate (not later), or the split view won't rotate correctly initially.

Resources