Reputation: 8484
Question 1:
How do I get the correct size of a UIView?
I am creating a CGRect to show some images using tiled layers.
When I'm creating the CGRect, I basically need it to be the exact same size as that of my UIView. This turned out to be quite hard..
When I NSLog() out my mainView.bounds.size.width
or my mainView.frame.size.width
they are always wrong when in landscape! They always log out the values as if it was in portrait, even though I can see the actual view being wider. And reversing them will also be wrong.
It's not good enough set the width to be the height and vice versa when in landscape, I need the right values.
The only way I've been able to make it look right is to manually put in 1024 for width when in Landscape, and this doesn't always work either, because:
Question 2:
What is the correct way to check if the device is in landscape or not?
I've been using
if([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft || [UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight)
but this doesn't always work. If I hold my device in landscape mode when launching, it is correct, but if I make it landscape, then lay the iPad flat down leaving the dashboard as landscape and THEN launch it, then the landscape-splash shows up, but that code think it's in portrait. That code doesn't work at all for iPad simulator either..
EDIT
For some reason, when I decided to add support for landscape orientation, it wasn't enough to just check the landscape-orientations in the summary-page of the target, I had to actually sub-class my TabBarController and physically tell it to rotate with
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
I shouldn't have to do this.. right? If I create an empty project like that, it doesn't need it.. I don't know why.
Upvotes: 0
Views: 246
Reputation: 25740
Question 1: Yup, that's right. :)
Question 2: I just got home and checked my own code. I use:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
to check the orientation of the current interface. Then, you can use something like:
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) {
// Do something
} else if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation)){
// Do something else
}
HOWEVER You really should not need to do this if you properly handle rotation events.
Here is my typical way of dealing with rotation when I need to adjust UI element positions in code based on orientation:
#pragma mark - View rotation methods
// Maintain pre-iOS 6 support:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
// Make sure that our subviews get moved on launch:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
[self moveSubviewsToOrientation:orientation duration:0.0];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self moveSubviewsToOrientation:toInterfaceOrientation duration:duration];
}
// Animate the movements
- (void)moveSubviewsToOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
{
[UIView animateWithDuration:duration
animations:^{
[self.tableView reloadData];
if (UIInterfaceOrientationIsPortrait(orientation))
{
[self moveSubviewsToPortrait];
}
else
{
[self moveSubviewsToLandscape];
}
}
completion:NULL];
}
- (void)moveSubviewsToPortrait
{
// Set the frames/etc for portrait presentation
self.logoImageView.frame = CGRectMake(229.0, 21.0, 309.0, 55.0);
}
- (void)moveSubviewsToLandscape
{
// Set the frames/etc for landscape presentation
self.logoImageView.frame = CGRectMake(88.0, 21.0, 309.0, 55.0);
}
I also put moveSubviewsToOrientation
in viewWillAppear
to have it rotate
Upvotes: 1
Reputation: 8741
I struggled with this a bit and here are some facts I found:
1- When a device is face up or down, the device reverts to the last orientation prior to it being face up or down since those 2 orientations do not tell you necessarily on their own whether the device is portrait or landscape. So for example, if you were in landscape and then put the device flat face up, then launch an app, it will launch in the landscape orientation.
2- When viewDidLoad is called, the bounds have not been set, so you need to put any calls that pertain to the orientation in viewWillAppear or viewDidLayoutSubviews.
3- If for some odd reason, you need to use the bounds before viewDidLoad, or maybe to do something in a model, I have found that the best way to put settings that pertain to the orientation is to trust the statusbar, which you can call as follows for example.
if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]))
PS: Regarding your added question, refer to: https://developer.apple.com/library/ios/#qa/qa2010/qa1688.html
You are most likely one of the last 2 bullets. I ran into this issue before and quite frankly found it easiest to just implement:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
for all VCs just to be on the safe side especially that the behaviour has changed from iOS5 to iOS6.
Hope this helps
Upvotes: 1