How can I refresh screen orientation in iOS - ios

In my app, some ViewControllers should be shown in fixed orientation but the others are free to rotate screen orientation. When I fix orientation on some ViewController using
NSNumber *value = [NSNumber NumberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
and this lock orientation well. However, when I back to previous ViewController or move to other ViewController which is free to rotate, orientation does not get back to real orientation.
I just release orientation lock when ViewController moves on, but [[UIDevice currentDevice] orientation] only returns value which I set value, not current device's real orientation. [UIViewController attemptRotationToDeviceOrientation] didn't work also.
How can I get current device's real orientation and refresh layout?
Thanks in advance.

Related

Is it possible to find out if an app UI is in landscape orientation after a device has been set down on a surface?

I'm determining a frame offset for a keyboard if the user is holding iPad in landscape mode. I'm finding that I'm unable to properly set the offset if I'm adding content in landscape mode and then set the iPad flat on a surface. I'm using the code below to set the offset:
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft || [[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) {
tableView.frame = CGRectMake(0,0,tableView.frame.size.width, tableView.frame.size.height-keyboardsize.height);
}
UIDeviceOrientations that I can check for are:
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
(source: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html)
Is there any way for me to check/know if a user has been holding the app in landscape orientation (UIDeviceOrientationLandscapeLeft or UIDeviceOrientationLandscapeRight) and then set the device down (which should be UIDeviceOrientationFaceUp)
What you're interested in is not the device orientation, but the interface orientation. Try using self.interfaceOrientation (where self is your view controller). You can also get this from [[UIApplication sharedApplication] statusBarOrientation].
That being said, you probably shouldn't be using the interface orientation at all to find out where the keyboard is. The keyboard generates notifications when it appears and moves around, which include position information. Take a look at the UIKeyboardWillShowNotification and UIKeyboardWillChangeFrameNotification. They have position information in their userInfo dictionary under the UIKeyboardFrameBeginUserInfoKey and UIKeyboardFrameEndUserInfoKey keys which will tell you where the keyboard will be.

iPad stop screen from Rotating Xcode 4

I am building an iPad app in Xcode 4. The app is suposed to always show in Landscape view. to achieve this I have tried the following:
In the Target summary screen I selecte only Landscape Left as a Supported Device Orentation.
In the Target Info screen / Info.plist set the Supported interface orientations(iPad) to Landscape (left home button)
This leads the app the to start in landscape mode, but if I rotate the device it still changes its orientation. Also, when I have a UIViewController presented with presentationStyle UIPresentationFormSheet it rotates to portrait the moment it shows.
In some other threads / forums it was adviced to create a category for UIViewController and rewrite
-(UIDeviceOrientation)interfaceOrientation;
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
To always rotate to the Device Orientation (LandscapeLeft) or specifically LandscapeLeft, also to no AutoRotate unless you rotate to LandscapeLeft.
When I set these functions like this (Or for example allow no rotation at all) the app always appears in portrait mode, and wont rotate, not even to LandscapeLeft. The only way to have the app start in Landscape mode is when I allow for rotation no matter what the interfaceOrientaton is.
Does anybody know how I can fix this?
The category I implemented:
#implementation UIViewController(Extends)
-(UIDeviceOrientation)interfaceOrientation
{
return [[UIDevice currentDevice] orientation];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
return YES;
else
return NO;
}
#end
The only place that I can find a Portrait Orientation to be defined is the original window on the MainWindow.xib, but this cannot be altered, and every thread/forum says that that particular setting is/should not be the issue.
As far as I can tell the steps you took should prevent rotation of the interface.
You can always try to override the calls that do the orientation in every viewcontroller of your app. That should at least give you a clue where the rotation is happening. After which a breakpoint can possibly tell you more.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
NSLog( #"will rotate to orientation %d in %#", interfaceOrientation, NSStringFromClass([self class])
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
NSLog( #"did rotate from orientation %d to %d in %#", fromInterfaceOrientation, [self interfaceOrientation], NSStringFromClass([self class])
}

Views moved out of place when rotating

I created a UIViewController (based on How to switch views when rotating) to switch between 2 views when the device rotates. Each view is "specialized" for a particular orientation.
It uses the UIDeviceOrientationDidChangeNotification notification to switch views:
-(void) deviceDidRotate: (NSNotification *) aNotification{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
NSLog(#"Device rotated to %d!", orientation);
if ((orientation == UIDeviceOrientationPortrait) ||
(orientation == UIDeviceOrientationPortraitUpsideDown)) {
[self displayView:self.portraitViewController.view];
}else if ((orientation == UIDeviceOrientationLandscapeLeft) ||
(orientation == UIDeviceOrientationLandscapeRight)) {
[self displayView:self.landscapeViewController.view];
}
}
and sort of works. The problems shows up when I rotate to Landscape and then back to Portrait. When going back to portrait the subviews aren't displayed in the right place, specially the UIPickerView:
First Time Portrait:
Rotate to Landscape:
Back to Portrait:
If I repeat the rotation process, things just get worse. What am I doing wrong?
The source code is here: http://dl.dropbox.com/u/3978473/forums/Rotator.zip
Thanks in advance!
To solve your offset problems, rewrite the displayView: method as below.
-(void) displayView: (UIView *)aView{
self.view = aView;
}
Rotations however are strange. you should review that part of code.
Use the UIViewController rotation methods
(void)willRotateToInterfaceOrientation:duration:
(void)didRotateFromInterfaceOrientation:
instead of -(void)deviceDidRotate:
Much simpler, you will avoid that strange bouncing, and you don't need notifications any more.
Do some reading on the apple documentation on the methods i specified above.
Hope this helps.
OK, I found the error. It's pretty simple and stupid: I mixed frame and bounds.
In the displayView: code I was setting the frame of the child view to the frame of the parent view, when it should be the bounds of the parent.

iPad orientation returns unknown values

I use this code:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
to get iPad orientation but it returns UIDeviceOrientationUnknown when I use OpenGL rendering. When I play movies or I display UIViews it return the correct value. Do you know how may I get correct orientation? I don't want to use the accelerometer because I want to know when the device has locked orientation.
Thank you!
There are situations where the accelerometer can’t get an accurate read on the orientation, such as when the device is held flat. You should still be able to get the current orientation using:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
In iOS 13, the statusBarOrientation has been deprecated. The new preferred way of getting this orientation is
let orientation = UIApplication.shared.windows.first?.windowScene?.interfaceOrientation
If I add [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; the orientation will be correct even in OpenGL rendering mode. UIDeviceOrientationUnknown orientation is sometimes returned but only for short time.

iPad Orientation/Frame size problem

In "View Did Load" I'm trying to determine the size of the view so I can appropriately size a subview. I want it to always stretch about the length and width of the screen regardless of orientation.
quest *anview = [[quest alloc] initWithFrame: CGRectMake(50, 50, self.view.frame.size.width-100, self.view.frame.size.height-100)];
self.aquest=anview;
But this always returns a width of 748 and a height of 1024 when it should return the opposite when I'm in landscape. I know that you can't get orientation on the simulator but this occurs on the device as well. When I get the orientation:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
NSLog(#"device orientation:%d",orientation);
I correctly get the orientation but this log statement returns the 748/1024 regardless of orientation.
NSLog(#"size w:%f",self.view.frame.size.width);
NSLog(#"size h:%f",self.view.frame.size.height);
Anyone know what's going on? Does this have to do with me putting this in the viewdidLoad method? Should I put it in viewWillAppear or viewDidAppear?
Try to use the bounds property instead of frame.
The view is always created in portrait mode and then rotated, even if you launch the application in landscape. You should be able to keep the subview stretched by setting its size relative to the parent's portrait size and the autorsizing mask to UIViewAutoresizingMaskFlexibleWidth|UIViewAutoresizingFlexibleHeight, providing the shouldAutorotateToInterfaceOrientation: return YES for the right device orientation. It will also keep the distance from the top and left margin unless you add to the mask a different UIViewAutoresizingFlexibleMargin.

Resources