Xcode Orientation change shows unwanted in between state - objective-c

I have a very strange problem.
I added orientation to my app for landscape and portrait without many problems and it works.
However, I noticed something weird.
When I keep my iPad "horizontal", meaning parallel to the floor, the view shifts in my window in a way that I did not define and it doesn't look good naturally. It shifts to an "in-between" state that I do not want (I don't know how to explain it otherwise).
Anyone experienced the same problem? And what is the solution to this problem?
For info: I used an observer on orientation change. I think this is where the problem occurred:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
I also used this code, but I didn't have problems with it before:
-(void)willRotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
[super willRotateToInterfaceOrientation:toInterfaceOrientation
duration:duration];
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
self.view=landscapeView;
self.view.transform=CGAffineTransformMakeRotation(deg2rad*(90));
self.view.bounds=CGRectMake(0.0,0.0,1024.0,748.0);
} else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
self.view=landscapeView;
self.view.transform=CGAffineTransformMakeRotation(deg2rad*(-90));
self.view.bounds=CGRectMake(0.0,0.0,1024.0,748.0);
} else if (toInterfaceOrientation == UIInterfaceOrientationPortrait){
self.view=portraitView;
self.view.transform=CGAffineTransformMakeRotation(deg2rad*(0));
self.view.bounds=CGRectMake(0.0,0.0,768.0,1004.0);
} else {
self.view=portraitView;
self.view.transform=CGAffineTransformMakeRotation(deg2rad*(180));
self.view.bounds=CGRectMake(0.0,0.0,768.0,1004.0);
}
}
Thanks!

Related

Is it possible to detect that an iPhone has rotated without the orientation of the view changing?

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.

how to detect the landscape mode on rotation in ios7?

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

iPad/iPhone orientation issue

I realize there a many questions relating to this issue, however i have not found one that solves my issue.
To start, I have set this code in my menu.h
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES; }
The status bar changes with orientation but the views are not rotating or resizing. In order to try to narrow down my issue, I decided to try to switch two views within one .xib based on orientation
- (void)viewDidLoad {
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
}
-(void) orientationChanged:(NSNotification *)object
{
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
In the iOS simulator, the view definitely changes to the specific views. However the landscape view shows up as if it was portrait and sideways.
my landscape view in IB
My landscape view in the iOS simulator after changing orientation
What am I doing wrong here? I can't figure it out, any help would be greatly appreciated. Thank you in advance.
** EDIT: New Code Below **
Okay.. my issue is that the view loads properly in landscape, it's just sideways. So the Landscape view loads, just sideways. My revised code based on #Seega is:
- (void)viewDidLoad {
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
[[TTNavigator navigator] setCustomTarget:self];
[[TTNavigator navigator] setCustomAction:#selector(photoAction)];
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIDeviceOrientationLandscapeLeft || toInterfaceOrientation == UIDeviceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
-(void) orientationChanged:(NSNotification *)object
{
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation == UIDeviceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
I would suggest putting your code in :
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
instead of making a new method. This will get called automatically if the shouldAutorotateToInterfaceOrientation method returns YES for that rotation.
Also there is a difference between UIDeviceOrientation and UIInterfaceOrientation so make sure your referencing the correct one. Your existing code would be changed to the following:
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
Also you can use a macro to check the interface orientation keeping your code cleaner.
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation))
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
Can you make sure, you have all the orientation support selected as follows. I tried this, and it seems to be working fine for me.
You should better simply use
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
self.view = self.landscapeView;
}
else
{
self.view = self.portraitView;
}
}
to handle the rotations instead of creating a own one.
And now you can delete all the notification stuff.
Idea!!!
If you are setting up the views in interface builder and then switching the actual view thats being displayed when the view rotates then you need to build that View in that particular orientation, not just size it to fit the orientation.
To check this:
Open your .xib in Interface Builder.
Click on the 'view' under objects so you have the whole view selected.
Look under the 'Simulated Metrics' on the right side of IB. Make sure 'Landscape' is selected in the 'Orientation' drop down.
If your view says 'Portrait' for the view you want to represent your landscapeView then it could be that xcode is rotating your landscape view to portrait and messing with your presentation.
Let me know if this helped.
Hey thank you all for your help. I had a friend help and am not entirely sure was the problem. I can tell you the things I know he did do.
Disabled our ads temporarily
deleted the second view entirely and went with native orientation and resizing
added this to almost every .m file.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
As well a programmatically changed a few of the other views similar to this
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIDeviceOrientationLandscapeLeft || interfaceOrientation == UIDeviceOrientationLandscapeRight)
{
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone)
{
self.Button.frame = CGRectMake(27,96,86,86);
self.Label.frame = CGRectMake(27,162,86,21);
}
else
{
self.Button.frame = CGRectMake(18,100,86,86);
self.Label.frame = CGRectMake(18,164,86,21);
}
}
}
Sorry, I can't fully explain the answer, I do not fully understand everything that was included in the project that affected the orientation. I am still very new to iOS development.

Landscape mode resizing

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!");
}
}

iPad Orientation Checking UIView Class?

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.