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])
}
Related
In the UIViewController rotation method(s) I have a problem when performing the device rotation
inside of the method
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
I am getting incorrect values
According to the documentation:
Sent to the view controller just before the user interface begins
rotating. Subclasses may override this method to perform additional
actions immediately prior to the rotation. For example, you might use
this method to disable view interactions, stop media playback, or
temporarily turn off expensive drawing or live updates. You might also
use it to swap the current view for one that reflects the new
interface orientation. When this method is called, the
interfaceOrientation property still contains the view’s original
orientation. Your implementation of this method must call super at
some point during its execution. This method is called regardless of
whether your code performs one-step or two-step rotations.
I am holding the device strait up (right after launching the app the device is physically in portrait mode) - all the views are correctly aligned for portrait mode
But in the method I am getting wrong values:
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// getting the wrong interface orientation here!!!!
// just checking the current orientation for debug
UIInterfaceOrientation currentOrientation = self.interfaceOrientation;
// the first time the device is rotated getting this value for current orientation:
// currentOrientation == UIInterfaceOrientationLandscapeRight
}
even worst than this strange case of wrong orientation is in this same method for 'will rotate to interface orientation' the current interface orientation and the destination interface orientation are identical i.e:
self.interfaceOrientation === toInterfaceOrientation
So whats the point of this method being called by the framework???
This results in all my UIView placement code not being calculating correctly on initial rotation of the device.
Why is this flag not set correctly?!?!
P.S
After rotating the device for the second time - the flags are set correctly and the views "align" themselves properly.
u will get correct value, suppose u are holding the device in port rite , then u turn it t landscape mode, then this method is called
//called first
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//check which orientation hear
if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
NSLog(#"turning t landscape");
}
else
{
NSLog(#"turning t portrite");
}
}
method called hear toInterfaceOrientation contains (for our example) UIInterfaceOrientationLandscapeRightorUIInterfaceOrientationLandscapeLeft`, this indicates that device will going to turn to landscape left or rite
after this, below methods called in order
- (void)viewWillLayoutSubviews
- (void)willAnimateRotationToInterfaceOrientation:duration:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
get called, hear in last method fromInterfaceOrientation contains (for our example) old value or previous orientation flag, that is UIInterfaceOrientationPortraitUpsideDown or UIInterfaceOrientationPortrait
u want t know the current orientation then u can use
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if(UIInterfaceOrientationIsLandscape(orientation))
{
NSLog(#"landscape");
}
else
{
NSLog(#"portrite");
}
for more information about this u can see this docs
My Storybuilder is designed with a portrait layout. When I start the app with my iPad already turned to horizontal, it's able to correctly detect it's in a horizontal position. But when I start the app with my iPad in a portrait position, it thinks it's in horizontal. However, every time I rotate it, the code is able to detect the correct orientation properly.
- (void) viewDidLoad
{
[self updateForOrientation];
}
- (void)updateForOrientation
{
if (UIInterfaceOrientationIsPortrait([[UIDevice currentDevice] orientation])) // became portrait
{
NSLog(#"is portrait");
//code for changing layout to portrait position
}
else //became horiztontal
{
NSLog(#"is horizontal");
//code for changing layout to horizontal position
}
}
Output: is horizontal (this is the output whether it starts up as portrait or landscape)
The problem is that you're sending the devices orientation in terms of the UIDeviceOrientation enum to a function that's expecting a UIInterfaceOrientation value.
If you command click on UIInterfaceOrientationIsPortrait(), you can see that it is defined as follows.
#define UIInterfaceOrientationIsPortrait(orientation) ((orientation) == UIInterfaceOrientationPortrait || (orientation) == UIInterfaceOrientationPortraitUpsideDown)
And if you look at the enum declarations for the two orientation types (documentation links below), you can see that there is a misalignment in value due to the device orientation containing a value for "none". Anyway, changing your code to use UIInterfaceOrientation should sort this out. Example:
- (void)updateForOrientation
{
UIInterfaceOrientation currentOrientation = self.interfaceOrientation;
if (UIInterfaceOrientationIsPortrait(currentOrientation)) {
NSLog(#"is portrait");
}else{
NSLog(#"is horizontal");
}
}
https://developer.apple.com/library/ios/documentation/uikit/reference/UIApplication_Class/Reference/Reference.html#//apple_ref/doc/c_ref/UIInterfaceOrientation
https://developer.apple.com/library/ios/documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html#//apple_ref/doc/c_ref/UIDeviceOrientation
Is there a possible way to autorotate the device orientation to portrait when the current orientation of the device is faceup or facedown?
You can use this trick to make the system refresh your controller orientation anytime you want:
[self presentViewController:[UIViewController new] animated:NO completion:NULL];
[self dismissViewControllerAnimated:NO completion:NULL];
This will call supportedInterfaceOrientations on your controller.
Just return UIInterfaceOrientationMaskPortrait when the device orientation is facing up or down and your controller's view will get adjusted accordingly.
Observe UIDeviceOrientationDidChangeNotifications to use the trick when you receive the notification and it's a face up/down device orientation, as those orientation do not correspond to UIInterfaceOrientations (and won't trigger supportedInterfaceOrientations).
Device and interface orientation definitions:
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
};
typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right
UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left
UIDeviceOrientationFaceUp, // Device oriented flat, face up
UIDeviceOrientationFaceDown // Device oriented flat, face down
};
You don't change the orientation. Instead, you tell iOS which orientations you support, so when the user rotates the device, iOS will switch the UI orientation to one that your application supports. The UI orientation should only change when the user rotates the device.
Use this code in your - (void)viewWillApper method
if(self.interfaceOrientation==UIInterfaceOrientationPortrait||self.interfaceOrientation==UIInterfaceOrientationPortraitUpsideDown)
{
//do something;
}
else
{
}
You can disable or enable rotation of the screen in portrait mode by set an appropriate value in the project settings (Targets -> General -> Deployment Info section).
mark the Portrait checkbox
mark the Upside Down checkbox (this enable Upside Down animation)
or
mark the Portrait checkbox
unmark the Upside Down checkbox (this is only Upside mode)
Use self.view.window?.windowScene?.interfaceOrientation.
This value will be either portrait, portraitUpsideDown, landscapeRight, or landscapeLeft.
See here for documentation.
I'm developing an iOS application with latest SDK.
My app only supports Landscape right orientation and it only has one view controller. I set the only available orientation modifying myProject-info.plist.
I'm trying to understand why this code outputs a log for a view in Portrait mode when I only supports landscape right orientation.
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
UIView *videoView = self.videoPreviewView;
NSLog(#"Video frame: %#", NSStringFromCGRect(videoView.frame));
}
Console output:
Video frame: {{0, 0}, {320, 568}}
I'm working with AVCaptureVideoPreviewLayer and I need to set its frame, but when I do it on viewWillAppear: I get portrait values but orientation value is Landscape right.
Is there an event or anything similar that i gets triggered when orientation changes to landscape?
When does the app changes orientation to default orientation?
Go into xCode, and click the project name at the top of the screen (with an xcode LOGO underneath it).
Then reveal the iPhone/Ipad development info and select the orientations you want to be available for users :)
If you add the line:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];
then it will call the -(void)orientationChanged; method every time the orientation is changed. You can then do something like:
-(void)orientationChanged {
if (UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) {
//device is portrait;
}
else {
//device is landscape;
}
}
Then you can use this to determine the layout of your views and setup based on the orientation.
EDIT:
You can also check if the orientation returned by the statusBar's orientation is equal to UIDeviceOrientationLandscapeLeft/LandscapeRight/Portrait/PortraitUpsideDown.
I have an app that supports orientation changes and rotates accordingly. I listen to the event UIApplicationWillChangeStatusBarOrientationNotification. Now during the load of this app I add some views and set them up in my app, based on the current orientation.
in iOS 6, this works fine and the app responds and rotates properly, so the user can load in both landscape and portrait mode and code works fine.
in iOS 5, if I load the app in portrait mode, the app works fine, and once that load has been completed in portrait mode, and the UI is aligned and sized, it will respond to other orientation changes to landascape or portrait. The problem I have is this : When loading iOS 5 in landscape mode, and while physically laying the device with iOS 5 on a flat surface to ensure its landscape, I get a OrientationNotification that moves from Landscape to portrait ( although the device didn't change ).
So another device iOS 6 in the same experiment, loads properly and I don't get any weird events of rotation changes that didn't occur, but with iOS 5 I do get them!!
Any ideas?
I am supporting the orientation for both iOS's
- (BOOL)shouldAutorotate {
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait ||
interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
It sounds like iOS 5 believes things should be portrait if, in fact, there is no physical orientation (i.e. flat up or down) and iOS 6 doesn't. For what it might be worth, to determine the orientation to display stuff when it matters, I use the actual device orientation when available and the status bar orientation when the device is flat. For instance:
// Get a useful screen orientation.
// If the device is physically in portrait or landscape then
// that is the orientation.
// If it is not, then it is probably flat on a table and use
// the orientation of the status bar which should be set to
// the last physical orientation.
//
// screen Orientation
//------------------------------------------------------------
+ (UIDeviceOrientation) screenOrientation {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation!=UIInterfaceOrientationPortrait
&& orientation!=UIInterfaceOrientationPortraitUpsideDown
&& orientation!=UIInterfaceOrientationLandscapeLeft
&& orientation != UIInterfaceOrientationLandscapeRight) {
// Not known at this time. Use the status bar orientation
orientation = [[UIApplication sharedApplication] statusBarOrientation];
}
return orientation;
}
I'm not sure that helps you directly, but perhaps in your notification handler you could check to see what the actual status bar orientation is. Or maybe the timing of the notification and the status-bar orientation change doesn't make that work.