Im developing an application to display a gallery of images by using a UIScrollView, the sliding between images works fine on portrait mode but when changed to landscape mode it shows the image plus a portion of the next image.
If i could get some explanation on how to solve this issue i would be very thankful.
Make sure your UIScrollView and it's parent view have the right UIViewAutoResizing and autoResizesSubViews values.
Then listen for device orientation changes and take appropriate steps (= reposition subviews of the scrollview)
-(void)applicationDidFinishLaunching:(UIApplication *)application {
// ... other things
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification" object:nil];
};
-(void)didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft) {
NSLog(#"Landscape Left!");
}
}
Related
In a nutshell, I want to manually rotate only a few elements on the screen when the device goes landscape but keep the actual app in portrait mode. How can I hinge on this event in the background?
Have you tried using
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
This only caters for device orientation, so if you have other orientations disabled. It still gives correct value for which ever orientation your device is in. You can compare its values to (and more, you can view those at https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIDevice_Class/index.html#//apple_ref/c/tdef/UIDeviceOrientation)
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationLandscapeLeft
I Hope this helps.
Edit :
For an event you have to add an observer to detect the device's orientation being changed. Register the notification/observer in appdelegate or where ever u feel it is needed and place orientationChanged method in the class where u delegated the observer. (probably in the same class in most scenarios).
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
- (void) orientationChanged:(NSNotification *)note
{
NSLog(#"orientationChanged");
UIDevice * device = note.object;
if(device.orientation == UIDeviceOrientationPortrait)
{
}
// add other else if here
else
{
}
}
Note that orientationChanged is called when you add the observer. Only once. After every time your device changes orientation. Do let me know if you find something confusing.
My app displays pdf pages,in portrait mode a single page is getting displayed(default mode is portrait).On rotating to landcscape it should display two pages side by side,
In my ViewController's viewdidloadmethod i have added the following,
- (void)viewDidLoad
{
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
landscape=UIDeviceOrientationIsLandscape(deviceOrientation);
if(landscape)
{
//logic goes here
}
else
{
logic for portrait goes here
}
}
But it's not working for me,only the portrait logic is getting excecuted.Please help
Orientation changes are handled a bit different way.
Your viewcontroller needs to receive notification, when orientation changes.
Here's the sample code:
#implementation PortraitViewController
- (void)awakeFromNib
{
isShowingLandscapeView = NO;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!isShowingLandscapeView)
{
isShowingLandscapeView = YES;
// logic for landscape orientation goes here
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
isShowingLandscapeView)
{
isShowingLandscapeView = NO;
// logic for portrait orientation goes here
}
}
For futher information, check Apple documentation
I have a subview in a subclass of UIView. When the device is rotated I want the subview to remove. This is my code:
- (void)awakeFromNib
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged) name:UIDeviceOrientationDidChangeNotification object:nil];
}
- (void)orientationChanged
{
[subview removeFromSuperview];
}
My problem is that even if the device is tilted a little bit, or put on for example a table the subview removes. What can I do to prevent this?
Don't track the device orientation. Track the interface orientation. Use UIApplicationWillChangeStatusBarOrientationNotification instead of UIDeviceOrientationDidChangeNotification, and get the new interface orientation out of the notification's userInfo. (You won't have to do beginGeneratingDeviceOrientationNotifications if you track interface orientation.)
How would I have one view up when the iPhone is in a standard 'portrait' orientation, and switch to a different view (say a graph or something) when rotated to a landscape orientation and visa versa?
Disable orientation for that view (assuming that the first view is landscape)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)||(interfaceOrientation == UIInterfaceOrientationLandscapeRight); }
Then add this to the viewDidAppear
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
And add this method somewhere
- (void) orientationChanged:(NSNotification *)note
{
UIDevice * device = note.object;
switch(device.orientation)
{
case UIDeviceOrientationPortrait:
// Present View Controller here
break;
default:
break;
};
}
And on the other view do the same but backwards with a dismiss for landscape instead of the present for portrait.
Dont forget to unregister for the notifications.
(alternatively use a navigation view with both controls but without the bar and simply show the one you want depending on the orientation using)
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
First read how UIViewControllers work:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
Then, in your UIViewController subclass, take advantage of willRotateToInterfaceOrientation:duration: to change out your views.
e.g.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// if portrait
[self.landscapeView removeFromSuperview];
[self.view addSubview:self.portraitView];
// if landscape
[self.portraitView removeFromSuperview];
[self.view addSubview:self.landscapeView];
}
And add in the appropriate if statement or switch case to determine which to do.
I have a UIView class which I add to my main UIViewController and I need to check the orientation of the device (iPad) at the launch of the app, in the viewDidLoad method. However because the class is a UIView (not UIViewController) I can't use methods such as willAnimateRotationToInterfaceOrientation.
So I attempted to use this in my UIView class:
if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) ||
([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) {
However, testing with some breakpoints, whatever the orientation is, the of statement is never called, its skips right passed it. So what do you suggest I do to overcome this issue?
I need to somehow detect the orientation from the UIView class.
Thanks.
Where are you placing the check? The location could easily explain why it's not being called. To get rotation info, you could register for a notification, or have your view controller call a method in your view. Sample code for the latter:
// ViewController.m
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self.customView willRotateToOrientation:toInterfaceOrientation];
}
// CustomView.m
- (void)willRotateToOrientation:(UIInterfaceOrientation)newOrientation {
// Handle rotation
}
The view controller method is one you override; the view's method should be declared in a header.
Update:
Alternatively, you can find out the rotation in the controller's `viewWillAppear':
// ViewController.m
- (void)viewWillAppear {
[self.customView willRotateToOrientation:[[UIDevice currentDevice] orientation];
}
The method in your view will be called accordingly.
One thing you can to is to register for orientation notification from NSNotificationCenter:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
...
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
// do things
}
This is however suboptimal since iPad may be laying flat on the table when app starts, and you'll get UIDeviceOrientationUnknown then. Been here, done that...
I ended up doing a trivial check like this:
BOOL landscape = self.bounds.size.width > self.bounds.size.height;
if (landscape)
// landscape stuff
else
// portrait stuff
But in my case the view changed aspect ratio upon rotation. If this is your case too, it should work fine.