UIView changes width after switching orientation to landscape? - iphone

I got a UIView with 2 subviews. The UIView is set to UIViewAutoresizingFlexibleWidth. Now when it enters layoutSubviews it resizes the frames of the subviews relative to the UIView like so:
rect.size.width = self.frame.size.width - rect.origin.x - textLabel.frame.origin.x;
But a problem occurs in landscape mode cause in portrait mode the self.frame.size.width (and bounds for that matter) respond 768 at start and 788 after it's done rotating. Meaning when it rotates it seems to add 20pixels which I assume is the status bar.
When I hard code 768 it all works as expected. But I don't want that of course. I could store the initial state into a var and use that but I don't think that's the right way to do it.
Anyone have a solution?

Greetings,
in my application I have been facing the same Problem. To solve it I simply used the didRotateFromInterfaceOrientation:method to resize the View when the device is rotated.self.view.frame = CGRectMake(0,0,self.view.bounds.size.width,self.view.bounds.size.height);
Hope this will help.

Related

What is the correct way to get screen width/height with orientation changes?

I'm currently using [[UIScreen mainScreen] bounds].size.width and height to get the screen width and height for getting a new image (that fills the screen) from a server. My problem is it appears that the bounds doesn't change on orientation changes. So if I rotate the device then it still gives me portrait width/heights even though the device is now in landscape. I'd like to not hardcode a screen width/height based on the current orientation. Is there a way that I can check the screen width and height that will correctly reflect orientation changes?
You can get the width and height by
int h = self.view.frame.size.height;
int w = self.view.frame.size.width;
Best way to do this is probably:
CGSize appSize = [UIApplication sharedApplication].keyWindow.rootViewController.view.bounds.size;
and also use appSize.height for height and appSize.width for width
This returns the orientation adjusted size of the topmost view which always fills the full screen, except possibly excluding the status bar depending on your status bar and wantsFullscreen settings.
[UIScreen mainScreen].bounds.size returns the bounds unrotated. You can use the convertRect:fromView: method (passing nil for the fromView) on an appropriate on-screen UIView to adjust for rotation and such.
I've been working on an app where we have run into problems like this on a few occasions, so I hope I can help:
First off, make sure you are using a UIViewController to manage your image.
Secondly, make sure your implementation of -shouldAutorotateToInterfaceOrientation: on that view controller returns YES.
Make sure you are using a UIImageView, not a UIImage for your picture, then try setting autoresizesSubviews on the image view's superview (this is the view controller's view) to YES.
If the image resizes, but not to your liking, try messing with the image view's autoresizingMask.
If, after step 3, the image doesn't autoresize, try implementing willRotateToInterfaceOrientation:duration: and programmatically setting the image's frame. Remember that it's superview (the UIViewController's view) hasn't rotated yet, so its frame hasn't updated.
Finally, if that doesn't work, try willAnimateRotationToInterfaceOrientation:duration:, though I'm not quite clear on the difference between this method and the former.
Hope this helps, and let me know your results!
-Bruce
try get your height and width from applicationFrame
UIScreen.mainScreen().applicationFrame.size.height

UIScrollView height adjusts from IB

I've created a UIScrollView in Interface Builder which takes up the entire screen of the iPad (0, 0, 1024, 768)
However - when running the app, the scrollView is only displaying on the screen at (0, 0, 1024, 440). The 440 is an estimate, but it is not extending all the way down to fill the screen as it should.
I've done this same thing in other apps and have not encountered this issue.
I've run "Clean" on the project and I've tried deleting the scrollView and recreating it and still the same issue occurs.
I even tried to programmatically reinforce what's in Interface Builder but still it showed up the same way.
CGRect scrollFrame = CGRectMake(0, 0, 1024, 768);
[scrollView setFrame:scrollFrame];
If you have any idea why this may be happening, your help would be GREATLY appreciated.
* UPDATE *
After some more research, there is something wrong with the view controller.
That area at the bottom where the scrollView isn't showing is totally not accessible. If I put a button toward the bottom of the screen, I can't click that button. If it's up in the top half of the screen I can click it just fine.
Also, the scrollview isn't really starting at 0, 0. Where it starts it is missing the top part of the content. So it seems like the scrollView DOES have the height of 768, but is starting at -320 so that the top of it is off the top of the screen and the bottom of it ends before the bottom of the screen.
The issue seems to have been that the app thought it was in Portrait mode even though I had the .xib in Landscape mode.
Fixed it with this little trick in the viewDidLoad of the mainProjectViewController:
CGRect landFrame = self.view.frame;
landFrame.size.width = self.view.frame.size.height;
landFrame.size.height = self.view.frame.size.width;
self.view.frame = landFrame;
Actually, viewing it in landscape mode is just a convenience for you to see what happens if you rotate the device. Launching in landscape mode can be problematic. See this question and its answers for some excellent info.

iPad frame width and height mixup in landscape

I have done what this question said here: Landscape Mode ONLY for iPhone or iPad
but the view.frame.size.height is still 1024, which is the height when the device is in portrait, surely when the interface rotates the width and height switch values?
(say you wanted to split the screen into 3 views, for an app that is both landscape and portrait, and you did view.frame.size.width / 3 , in landscape that wouldn't be correct as the width value wouldn't actually be the width)
I'm sure on the iPhone the width and height switch, so why not on the iPad?
This has struck me again I 'm not working with a nib either, could someone please give an acceptable answer? (ie one that doesn't involve manually switch the width and height)
Once the bounty has been awarded to an answer, I will then start another bounty for 250 and award it to the same person.
You haven't specified which "view" you're querying. Assuming this is the top level subview of the window:
You should query the view's bounds not its frame. frame is in the coordinate in which the view is defined (the outside world) hence may remain constant as you rotate. bounds is the coordinate used "inside" the view and for its subviews. This does change when you rotate.
+ (int) currentWidth
{
UIScreen *screen = [UIScreen mainScreen];
int width = screen.currentMode.size.width;
int height = screen.currentMode.size.height;
return (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))? MAX (width, height) : MIN (width, height);
}
I spent a while trying to work out the simplest solution to a frustrating problem, and this was the best I could come up with. Hope it can help.

UIView parent window's frame and bound dimensions while rotating iPad

I a have a following line of code invoked after a touch gesture has completed:
CGRect parentBounds = self.view.bounds;
CGRect parentFrame = self.view.frame;
when iPad is placed in a vertical way both parentFrame and parentBounds have similar dimensions of w:768 h:1004 (or something close to that), but when I rotate parentBounds is 1024x748 while parentFrame is 768x1024.
Is this behavior normal? I thought I understood the concepts beetwen frames and bounds (and how they relate to each other)... but now I am really confused.
Could anyone explain what is happening with frame and bounds of a window (superview) when rotation occurs?
The window does not change orientation; the root view does. It does this by applying a view transform (self.view.transform). You're not supposed to call frame if transform is not CGAffineTransformIdentity.
This is not a complete answer, but might help if you don't get something better: When the device is rotated, the top-level window's frame does not change. Instead, a transform gets applied that rotates everything 90 degrees (or 180 degrees), and then the subviews will get resized to fit in the new coordinate system.
From Apple's PhotoScroller sample code:
We have to use our paging scroll view's bounds, not frame, to calculate the page placement. When the device is in landscape orientation, the frame will still be in portrait because the pagingScrollView is the root view controller's view, so its frame is in window coordinate space, which is never rotated. Its bounds, however, will be in landscape because it has a rotation transform applied.
In short, the view's frame is not affected by device rotations, but its bounds is.

"Incorrect" frame / window size after re-orientation in iPhone

In my iPhone OS application I want (need) to watch for changes in the device orientation in order to rearrange certain portions of the screen. The approach I used was to use CGRect frame = [UIScreen mainScreen].applicationFrame to get the screen size, and from there calculate the size and / or positioning of other controls (I also tried self.view.frame).
All testing was done so far in Portrait mode, so I could focus on programming the main features and later on just do some adjustments for Landscape. And here enters the problem: In -(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation I added some logging to check the sizes before proceeding, but apparently the values for Width and Height are "wrong" (I say "wrong" because at a first glance the values does not make sense to me).
Here's the output of some logging:
Rotation: Landscape [w=300.000000, h=480.000000]
Rotation: Portrait [w=320.000000, h=460.000000]
The values for "w" and "h" in Landscape seem inverted to me - I was expecting that w=480 and h=300.
What am I doing wrong? The code I used to debug is below.
-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
CGRect frame = [UIScreen mainScreen].applicationFrame;
CGSize size = frame.size;
NSLog(#"%#", [NSString stringWithFormat:#"Rotation: %s [w=%f, h=%f]",
UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? "Portrait" : "Landscape",
size.width, size.height]);
}
The orientation of your device changed, not the physical characteristics of the screen. You basically tipped it on its side, but in reality it is 320 pixels wide (20 of which are not available to you at the moment since the status bar is showing) and 480 pixels tall. If your view is auto-rotating, then the width/height have been translated for you, but when you ask for the actual dimensions of the screen, you get back the actual dimensions of the screen.
This is also why, when working with translated views, it is important to do calculations based on the view's center and the view's bounds and never on the view's frame.
Use self.view.bounds instead.
I've been stumbling over the same problem and with some diagnostic work I discovered that the view's bounds and frame do not accurately reflect the landscape orientation in viewDidLoad (when the device is held in landscape when the view controller is pushed onto the stack), but do so correctly in viewWillAppear: and viewDidAppear:. I just moved my code that needed the dimensions of the frame/bounds from viewDidLoad to viewWillAppear:, and it worked properly.