I do some custom layout including an animation in willAnimateRotationToInterfaceOrientation:duration:
The problem I have is that if the device changes from landscapeLeft to landscapeRight the interface should rotate but the layout code, especially the animation should not be run. How can I detect that it is changing from one landscape to another? self.interfaceOrientation as well as [[UIApplication sharedApplication] statusBarOrientation] don't return valid results, they seem to think the device is already rotated. As a result the following does not work.
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation) && UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) {...}
You can check the device orientation and then set a flag as to whether you are in left orientation or right orientation. Then when your device switches you can catch it and handle it however you want.
To determine orientation use:
if([UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft)
{
//set Flag for left
}
else if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)
{
//set Flag for right
}
You can also catch a notification when the device is rotating using:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(detectOrientation) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
And then write a method for detectOrientation like so:
-(void) detectOrientation
{
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft)
{
//Set up left
} else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)
{
//Set up Right
} else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown)
{
//It's portrait time!
}
}
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft || [[UIDevice currentDevice] orientation ]== UIDeviceOrientationLandscapeRight)
{
NSLog(#"Lanscapse");
}
if([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown )
{
NSLog(#"UIDeviceOrientationPortrait");
}
}
It seems that the only solution is to cache the last orientation change. By the time willAnimateRotationToInterfaceOrientation: is called the device and interface orientations have already been updated. The solution is to record the destination orientation at the end of each change so that this value can be queried when the orientation is set to change again. This is not as elegant as I was hoping (yet another property on my view controller) but seems to be the only way as far as I can tell.
Related
I'm writing a program that detects a change in orientation of the device (portrait to landscape, etc.). When the device is in portrait a collectionview should be displayed and a scrollview should be hidden. When the device is in landscape mode the collectionview should be hidden and the scrollview should be displayed.
Through NSLogs I have confirmed that rotating the device is detected. and the hidden property is being set to YES.
I has essentially the same code working with two scrollviews, but due to performance issues I switched to using a collectionview and now it doesn't work. Any advice would be much appreciated. Thank You!
I have this code in the viewDidAppear method:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(detectOrientation) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
And this code in the detectOrientation method
-(void) detectOrientation {
if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) ||
([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) {
[myCollectionView setHidden:YES];
myPanoramicScrollView.hidden = NO;
NSLog(#"collectionView.hidden = %hhd", myCollectionView.hidden);
} else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait) {
myPanoramicScrollView.hidden = YES;
[myCollectionView setHidden:NO];
NSLog(#"collectionView.hidden = %hhd", myCollectionView.hidden);
}
}
I have a Navigation controller that takes a user to another view and lays out the new view based on which button the user clicked on and the orientation. I have a method called layout and I call this method in viewDidLoad, viewWillAppear, and willAnimateRotationToInterfaceOrientation
However, when the view is first loaded, the app does not recognise it's in Landscape. The code I have is:
UILabel *shareLabel = [[UILabel alloc] initWithFrame:CGRectMake(488, 90, 179, 30)];
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
shareLabel.frame = CGRectMake(543, 90, 238, 30);
}
I've even tried putting a break point on the if statement, and when it gets to the if statement, it steps over it, which tells me it's not recognising that it is landscape? Any ideas on why this would be?
Check this out
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
if ( ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait) )
{
// do something for Portrait mode
}
else if(([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) || ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeLeft))
{
// do something for Landscape mode
}
Is anyone know a way to detect the orientation of the iPad programmatically when launch a app.
I'm using following mechanism.
- (void) detectDeviceInitialOrientation
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
MyAppDelegate *appDelegate=(MyAppDelegate*)[[UIApplication sharedApplication] delegate];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (UIDeviceOrientationIsPortrait(orientation)) {
appDelegate.orintation = PORTRAIT;
}
else if (UIDeviceOrientationIsLandscape(orientation)) {
appDelegate.orintation = LANDSCAPE;
}
}
But it fails to detect the device's orientation when it lay parallel to the floor. So, I'm looking another solution. Please help......
Have a look at the UIDeviceOrientation enum in the docs.
typedef enum {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
} UIDeviceOrientation;
Notice that this defines UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown. Unfortunately, there is no built in check for whether the device is in one of these orientations like there is for portrait or landscape. However, you can do the checking your self with a simple if statement. Something like this:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationFaceUp || orientation == UIDeviceOrientationFaceDown) {
// device is flat on the ground
}
I have the following code to fill a view according to the orientation. This always returns landscape.
- (void)setData:(BCPlaylist *)list {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown){
NSLog(#"portrait");
[self setPlaylist:list];
[self renderPlaylist];
[activity stopAnimating];
}else{
NSLog(#"landscape");
[self setPlaylist:list];
[self renderPlaylistOne];
[activity stopAnimating];
}
}
I change views correctly in - (void)animateRotation:(UIInterfaceOrientation)interfaceOrientation
duration:(NSTimeInterval)duration {
But that doesn't work when already in landscape or portrait when changing a playlist.
Instead of using [[UIDevice currentDevice] orientation] for checking orientation use statusbar orientation to get the exact orientation.
UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
To avoid a warning, use :
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
You'd always get landscape, because that's your default (from your if statement). If you walk through the debugger with a breakpoint there, you'll see that the orientation reported is that of Unknown.
In fact, your code is fine, but this is a limitation of the simulator. If you take the same code, using Device orientation and not Interface orientation, you'll get actual values if you use it on the physical device, which can be driven by the if-statement you have.
a noob question here.
i detect the orientation with:
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
all is fine and dandy and I reposition my text fields and labels according to the reported orientation with
if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown)
and else{} for everything else
the problem that i only recently discovered is when the UIDevice reports UIDeviceOrientationFaceUp or UIDeviceOrientationFaceDown. how do I deal with this situation ? how do I know whether UIDeviceOrientationFaceUp and UIDeviceOrientationFaceDown is happening in Portrait or Landscape ? I know that the device is facing up or down, but I don't know if I should reposition everything to Portrait or Landscape.
thank you!
Apple recommends against using device orientation for view layout. Instead, each view controller has an interfaceOrientation property, and UIApplication has a statusBarOrientation property, both of which will return the current interface orientation, which is suitable for view layout.
To monitor for changes, there are UIViewController methods like willRotateToInterfaceOrientation:duration: that will be called and notifications such as UIApplicationWillChangeStatusBarOrientationNotification that will be posted when an interface orientation change occurs.
A bit late, hopefully it would help some one.
For iOS 6.0 and later:
1) Set this code during your View Setup to receive rotation notification:
// Set Listener to receive orientation notifications from the device
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(detectOrientation)
name:UIDeviceOrientationDidChangeNotification
object:nil];
2) Set this code to catch the Notification after rotation:
-(void)detectOrientation{
switch ([[UIDevice currentDevice] orientation]) {
case UIDeviceOrientationFaceDown:{
NSLog(#"UIDeviceOrientationFaceDown");
break;
}
case UIDeviceOrientationFaceUp:{
NSLog(#"UIDeviceOrientationFaceUp");
break;
}
case UIDeviceOrientationLandscapeLeft:{
NSLog(#"UIDeviceOrientationLandscapeLeft");
break;
}
case UIDeviceOrientationLandscapeRight:{
NSLog(#"UIDeviceOrientationLandscapeRight");
break;
}
case UIDeviceOrientationPortrait:{
NSLog(#"UIDeviceOrientationPortrait");
break;
}
case UIDeviceOrientationPortraitUpsideDown:{
NSLog(#"UIDeviceOrientationPortraitUpsideDown");
break;
}
case UIDeviceOrientationUnknown:{
NSLog(#"UIDeviceOrientationUnknown");
break;
}
default:{
break;
}
}
}
I have the same problems with
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
This method generate notifications for 7 possible device positional states:
UIDeviceOrientationPortrait
UIDeviceOrientationPortraitUpsideDown
UIDeviceOrientationLandscapeLeft
UIDeviceOrientationLandscapeRight
UIDeviceOrientationFaceUp
UIDeviceOrientationFaceDown
UIDeviceOrientationUnknown
But I only need the first 4, well this is my approach to solve this problem (with code included):
How to handle UIDeviceOrientation for manage views layouts