I have a ebook reader app where in, i need to programmatically adjust the device orientation according to the layout of the page... i.e, The device should support all orientations for some pages and only landscape for some other pages. Is there anyway in which i can force a orientation change programatically
You can use the answer from jbat100 plus a call to setStatusBarOrientation:animated in UIApplication to achieve the effect.
Note that the behavior for this has changed as of iOS 6.0. For further info, see: Autorotate in iOS 6 has strange behaviour
The gist is that should/will/did/etc have been deprecated and have been replaced with a cleaner, more dynamic implementation. Which we should all be thankful for.
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
This can set the device orientation to LandscapeRight programmatically.
You cannot force the device orientation to some value, the system tells you the device's orientation, not the opposite. You can rotate your views using CGAffineTransform and such (a related post here).
Actually you can force any rotation. At least I was able to do it. Solution I used: https://stackoverflow.com/a/10146270/894671
This works for me on Xcode 6 & 5.
- (BOOL)shouldAutorotate {return YES;}
- (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}
Related
My app has navigation bar, where 1st screen returns YES to orientation, the second one is set to some orientation basing on what user choose in 1st screen. After going back to 1st screen from 2nd one, if user had device in hand in portrait but interface was in landscape, 1st screen is set to landscape. This happens because of
(BOOL)shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation
Is called only after changing device orientation.
I want to check what is device orientation atm and set interface orientation to this one.
Tried:
//1st method:
UIViewController *rotateTheScreen = [[UIViewController alloc]init];
[self presentModalViewController:rotateTheScreen animated:NO];
[self dismissModalViewControllerAnimated:NO];
[rotateTheScreen release];
//2nd method:
UIInterfaceOrientation interfaceOrientation = self.interfaceOrientation;
//3rd method:
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
1st is acting strange, rotates all cases besides coming back from interface orientation = landscape and device orientation = landscape (here is a bug, he rotates to landscape)
2nd checks interface, like the name tells, and tho doesnt work for my problem
3rd as far as i heard is private and Apple rejects apps using this.
Take a look at this thread.
Basically, there's no way to force a device orientation and get your application approved by Apple.
Shortly, the method exists but is an undocumented method of the UIDevice class.
[[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight animated:YES];
This gives a compiler warning that you can get rid of with a category.
#interface UIDevice (MyAwesomeMethodsThatAppleWillNeverAllowMeToUse)
-(void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated;
-(void)setOrientation:(UIInterfaceOrientation)orientation;
#end
Also, some say that you can call these methods indirectly using performSelector to get around Apple's static code analysis, as you can read in the comments here.
as I know there are no legal way. If I wrong, please, correct me somebody!
change the 'Initial interface orientation' in your project plist file
I want my iPad app to stop rotation as you rotate the iPad. I want to stop rotate every view.
Any ideas help?
if you want stop rotation for whole app then simply in app info.plist file changed Supported interface orientations ,Initial interface orientation property to portrait or landscape depends on you
In iOS6 shouldAutorotateToInterfaceOrientation has be deprecated. Override both supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation instead.
Please see
Just check the auto-resizing property of your view controller.
(Fixed syntax error)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(interfaceOrientation == UIInterfaceOrientationPortrait)
return YES;
return NO;
}
In My Project's info.plist I have deleted some key on the iPad Supported interface orientations like the following image (I have only given support for the portrait orientation)
The main idea of global controllable rotation lock is to write UIViewController category containing lock mechanism for every view controller.
You simply need to modify supportedInterfaceOrientations method globally
- (NSUInteger)supportedInterfaceOrientations
{
return __orientation;
}
Here __orientation is the static variable which can be set via category method.
The full realization of the category is presented here
Please update your projectname.plist like this. Supported interface orientations have only one object "Portrait (bottom home button)"
I strongly advise against stop rotation on iPad because supporting rotation is a must on the iPad. This is because the iPad does not have a normal way in which it will be held unlike the iPhone, which is normally held in portrait view (AKA Vertical). So you have to leave the choice to the user to eventually lock the orientation
The HIG do not actually state this as a requirement, but as a recommendation but there are many app that was rejected by this issue.
By the way if you want to this for a limit number of view controller you should implement:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(interfaceOrientation == UIInterfaceOrientationPortrait){
return YES;
}
}
How to find out if the UIDeviceOrientationFaceUp is landscape FaceUp or Portrait FaceUp?
Can any one tell me?
UIDeviceOrientation will only tell you the orientation of the physical device. You need to use methods that use UIInterfaceOrientation (from UIApplication) to make decisions depending on whether the screen is in portrait and landscape mode.
You can use UIInterfaceOrientationIsLandscape() and UIInterfaceOrientationIsPortrait() with a UIInterfaceOrientation too.
I realise this is an old question now, but looking at the answers everyone is being overly pedantic. In case anyone else stumbles across this:
The answer to your problem is for you to keep a secondary variable which is any of your accepted orientations.
When the device orientation notification comes in, simply look at the incoming orientation and see if its an acceptable one, (portrait/landscape NOT faceup/facedown) then update your secondary variable, and finally trigger a ui/app refresh from there using your secondary variable as the orientation source.
This will have the effect of locking the orientation to the "last known good" orientation.
It's not possible, because the accelerometer can't detect rotation around the z axis. On an iPhone 4, you could perhaps use the gyroscope for this (using CoreMotion), but UIDevice doesn't have an API for this. You would then also have to define what the starting position is, because you can't detect in which direction the user is from the device's point of view.
UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown are orientations for when the device is laying flat (like on a table). Portrait and Landscape don't make sense in this cases.
There is no way you can find out from orientation . I have found a workaround.
CGRect screenBounds = [[UIScreen mainScreen]bounds];
if(screenBounds.size.width > screenBounds.size.height)
{
// This means FaceUP/Down is in Landscape
}
else
{
// This means FaceUp/Down is in Portrait
}
I am using the following code to set the device orientation
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
when i used i got the warning and i found the below code to fix that warning.
#interface UIDevice (MyPrivateNameThatAppleWouldNeverUseGoesHere)
- (void) setOrientation:(UIInterfaceOrientation)orientation;
#end
Now what i would like to know is ...
Can the app store accepts this code to be in an application?
Thanks for any help!.
oh god, no. The warning you're getting is because this is not a readwrite property; merely adding a category that declares the method will not let you set the orientation. Not only will the AppStore not accept this, it will crash the first time it's called, as there's no accessor. (well, it will PROBABLY crash. There may be an undocumented API here, in which case you'll JUST get rejected).
If you are trying to rotate the view programmatically, you should look at shouldAutorotateToInterfaceOrientation and if you just want the App to be of a specific orientation, try using UIInterfaceOrientation set in plist.
Another useful post:
Forcing UIInterfaceOrientation changes on iPhone
Instead of setting an orientation, the proper way to do it is by having your application listen for when the user rotates the phone, then return YES or NO to indicate that the app should, in fact, rotate (i.e. always return NO if you want the app to always remain in its initial state.) The shouldAutorotateToInterfaceOrientation: method is automatically called whenever the user changes orientation.
For example, in your view controller, implement the method to only allow the phone to be used in landscape right/left:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if (UIDeviceOrientationIsLandscape) { return YES };
return NO;
}
You will also want to set your app's default orientation (so it doesn't start in portrait mode) by adding the UIInterfaceOrientation tag to your app's info.plist file with the value UIInterfaceOrientationLandscapeRight. Otherwise, the default value is portrait, and the user will have to tilt the phone to get it into the expected orientation.
I don't need to specify the orientation in this case, I just need to detect it, but I'm having trouble. I have conditional code that should only work in portrait, and if the device is in landscape I need to do something else. Since the deviceOrientation is not necessarily the same as the interfaceOrientation, I can't come up with a way to test for portrait mode.
Most tutorials I find on Google are ways to force landscape or do some sort of rotation. The only thing I want to do is just determine what the orientation is. Here is my code, which is not working:
-(void)viewDidLoad {
[super viewDidLoad];
//currentOrientation is declared as UIInterfaceOrientation currentOrientation
currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
NSLog(#"%#",currentOrientation); // == NULL
}
I need to determine the value of the interfaceOrientation and program conditionally. Thanks for your help!
Are you aware of the interfaceOrientation property of the UIViewController class?
- (void) viewDidLoad {
[super viewDidLoad];
BOOL isPortrait = UIDeviceOrientationIsPortrait(self.interfaceOrientation);
// now do whatever you need
}
Or are you after [[UIDevice currentDevice] orientation]?
Especially at launch I have found the following to be always accurate for the UI, regardless of what the UIDevice says the orientation is.
[UIApplication sharedApplication].statusBarOrientation
self.interfaceOrientation is unreliable in certain situations. For example, re-arranging tabs in a tabbar application returns incorrect value.
However [UIApplication sharedApplication].statusBarOrientation is always reliable. You saved me a lot of time slycrel. Thank you.
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if ((orientation == UIInterfaceOrientationLandscapeLeft)
|| (orientation == UIInterfaceOrientationLandscapeRight) )
{
//Landscape
}
else
{
//Portrait
}
I know it is a very old post. How ever I would like to add a point to say it is better to check status bar orientation is better. When ever you call self.interfaceorientation it is calling shouldRotateToOrientation every time. If you have written some code in that method it will be executed. So be cautious!.
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(deviceOrientation == UIDeviceOrientationFaceUp || deviceOrientation == UIDeviceOrientationFaceDown){
if(debug){
NSLog(#"Nothing to change because it is gone to Flat");
}
return;
}
if(deviceOrientation !=statusBarOrientation){
if(debug){
NSLog(#"\nApple has a bug?:\n UIDeviceOrientation : %d, UIInterfaceOrientation: %d",deviceOrientation, statusBarOrientation );
}
}
You won't believe me until you will see at the console the second output!
Some situations - and they exists! - is displayed the last NSLog content!
Than you have to do some workarounds to go on that way, where iOS has no bug, good luck for everyone!
Ah that ... forum moderator maybe will delete this post too, because this doesn't meant to be and answer in his opinion!
I hope it helps for somebody once, it happens on iphone too...(there I got)
Mix it up a little:
BOOL isLandscape = self.view.frame.size.width > self.view.frame.size.height;
(edit) Obviously the previous answers are the correct way to do this and this solution would fail in a situation where view controllers are not full-screen.
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{</br>
if (UIDeviceOrientationIsLandscape(toInterfaceOrientation)) {</br>
some instructions;
} else {
some instructions;
}
}
This is a snippet from one of my programs.
You could of course use the if statement in your ViewDidLoad notification as well.
I already voted up the answer by #slycrel, but I would like to take the time to write this, and point some things out that seems to be lost in this old question, and lots of other questions on the subject.
It's true that Apple does not really want us to update most of our UI based on orientation changes, but it is still totally possible and sometimes necessary on a case by case scenario, and it will be that way until Apple improves their new(ish) APIs (e.g. viewWillTransitionToFrame: would be way more useful than viewWillTransitionToSize:. Just sayin')
Why I voted up the answer by #slycrel is related to what you need to keep in mind as the logical difference between UIDeviceOrientation and UIInterfaceOrientation.
Tthe status bar is what denotes an application's currently known UIInterfaceOrientation. All this stuff about FaceUp, FaceDown is only related to a device's orientation, not necessarily your application's. An application does not support device orientations anyway. Really, UIDeviceOrientation can be ignored completely if all you have to do is make sure you layout and animate things appropriately in your interface, which is 99% of an application developer's use cases. This is currently achieved with the status bar's UIInterfaceOrientation from #slycrel's answer:
[UIApplication sharedApplication].statusBarOrientation
It should be noted, the readwrite version of this property is deprecated, the readonly version is not.
Take this example:
I have an application that supports ALL interfaces orientations, and a root view controller that supports them as well.
Now, I am presenting a UIViewController that will result in the status bar orientation to become landscape.
Which landscape orientation (left or right) it goes to is based on what is returned by preferredInterfaceOrientationForPresentation for that view controller, what the current device orientation is, and what interface orientations the view controller supports (see next point).
The status bar will go to landscape, regardless of what the current device orientation is, because this view controller only supports landscape based on what is returned by supportedInterfaceOrientations. Lets say we support both landscape left and right with UIInterfaceOrientationMaskLandscape.
I also want to conditionally animate this view controller into position with a rotation transform. This will only be necessary when going from portrait or portrait upside down, to landscape left or landscape right. Otherwise it will be a more simple presentation animation without rotation.
Then, after some time and device use, I dismiss that view controller.
Now I want to conditionally animate this view controller off the screen with another rotation transform. This will only be necessary when going from landscape left or landscape right, to portrait or portrait upside down. Otherwise it will be a more simple dismissal animation without rotation.
At this point, the status bar's orientation will become whatever the system decides is appropriate for the combination of your root view controller's preferred interface orientation and supported interface orientations, as well as the device's current UIDeviceOrientation.
Since the view controller we are going to supports ALL interface orientations, if your device's orientation is FaceUp or FaceDown, you can not reliably guess the next UIInterfaceOrientation based on UIDeviceOrientation, and you do not have to anyway.
So... status bar orientation to the rescue!
The previous example is possible, because the status bar orientation is not updated when a view controller transition is about to start (the system asks a transition delegate for an animator, etc.). Then it is updated when the transition starts animating (e.g. by the time animationTransition: is called). This way you should have a good comparison just using the initial and current values of the status bar's UIInterfaceOrientation.
Even without using view controller transitions, it should still be safe to update views based on the status bar orientation.
Keep in mind, if you are manually updating the status bar, and if you are not using "View controller-based status bar appearance" in your Info.plist, then your application's logic must be aware when the status bar will and did change orientation. You will probably be looking for a couple NSNotification names for these cases, which are:
UIApplicationWillChangeStatusBarOrientationNotification
UIApplicationDidChangeStatusBarOrientationNotification
As well as these UIApplicationDelegate methods:
- (void)application:(UIApplication *)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration;
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation;
- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window
And this other helpful UIApplication property:
#property(nonatomic,readonly) NSTimeInterval statusBarOrientationAnimationDuration;
As of iOS8, APIs have been deprecated or return unhelpful results such as .FaceUp .FaceDown
This is because Apple does NOT want you to update your UI using orientation, but rather by using size classes, constraints, and proportion (using n% of superview).
Indeed, orientation dependent code might fail to provide good results across the whole range of device and use case (especially multitasking)