In my app, I am dynamically using self.view.bounds to position subviews and I am not using Autolayout. When the view is rotated to portrait mode on iOS 8, I see self.view.bounds to be {568, 320} after view appears as opposed to natural behavior of {320,568} on iOS 7. How do I get this right ?
EDIT : I forgot to mention where I am doing this. This happens in viewDidAppear:. The value of self.view.bounds is incidentally correct in viewWillAppear but somehow it gets screwed up in viewDidAppear:.
EDIT 2: Here is I found on further drilling. Following is the scenario unique to my code :
a. Auto rotation is BLOCKED by me in code by returning only landscape orientation when the view is starting (this has to do with the camera & opengl setup I am doing and I do not want to autorotate the interface till everything is setup,
b.The view is freeform in XIB and has flexible width, height and all the edges in autoresizing mask.
c. Based on the above resize mask, iOS 7 gives self.view.bounds size equal to {320, 568} even though auto rotation has not happened. iOS 8 somehow ignores the same resize mask & the bounds is still {568,320}
So the root of the problem is UIWindow is autorotating in iOS 8 with the device while View controller is denying to autorotate.
In iOS 8, the rectangle returned by [[UIScreen mainScreen] bounds] takes into account the rotation of the device. No longer will the portrait frame be returned when the device is in landscape.
The updated-for-iOS-8 docs for UIScreen -bounds state:
This rectangle is specified in the current coordinate space, which takes into account any interface rotations in effect for the device. Therefore, the value of this property may change when the device rotates between portrait and landscape orientations.
Prior to iOS 8, the discussion section simply said:
Contains the bounding rectangle of the screen, measured in points. (read-only)
Related
My UIViewshould always be in fullscreen but that doesn't really work sometimes. Every time the user rotates the device, the method viewWillLayoutSubviews gets called.
Here I print the height and width of the UIView.
The height and width of the UIView are right (1024 width,768 height in landscape mode).
Anyway, on the iPad the View hasn't this size altough I write it to the Console.
In portrait mode everything works, but in landscape not so what could be the problem?
If the iPad is in landscape mode and I start the app it works but if I rotate it (then it's portrait) and rotate it back to landscape, the view isn't in fullscreen anymore.
Simply pin the edges of your UIView to the edges of the view controller's main view with constant of 0, once when you add the UIView to the interface, and all will be well thereafter.
I need to handle all iOS screen ratios (3.5 inches, 4 inches). I am not using autolayout because I need iOS 5.x compatibility.
In my app I need to reorganize my buttons and icons when device orientation changes, switching from Portrait:
Logo
-
Button 1
Button 2
Button 3
to Landscape :
Button 1
Logo Button 2
Button 3
Because of the different screen ratios, I need to adjust height of the Logo in Portrait based on the Y-position of Button 1, and to adjust width of the Logo in Landscape based on the X-position of Button 1.
To provide smooth animation, I would like to implement :
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)
and start an animation that would run in the same timeline than the device's rotation animation. The problem is that I need the target frame of "Button 1" for my computation (the frame after the device rotation) and I only have the frame of its initial state.
If I wait for the initial rotation to complete (which is what I implemented so far), you see that the app performs the rotation and THEN the positioning, which is... not satisfying for me.
So, in one single question, that would give :
"Is there a way to ask for the frame of a UIView given a specific device orientation ? Maybe the storyboard..."
It should be accessible somewhere, because the iOS animation has to compute this information to start its animation right ?
One way to find the screen bounds is to do the following:
CGRect screenBounds = [[UIScreen mainScreen] bounds];
We are just putting user input into our game so the user can enter email address etc. The entire game is Gl with no iOS UI at all. The EAGLView does not change orientation, it is always in portrait, however the game is in landscape and we handle this with a camera transform.
We want to bring up the iOS keyboard and overlay a UITextView for the text input. The UITextView is a subview of the EAGLView. Obviously it, and the keyboard, shows up in portrait as the EAGLView is in portrait.
Without having to change the EAGLView to landscape is there any way I can force the UITextView and the keyboard to show up in landscape orientation?
If I do change the orientation of the EAGLView to landscape to get this working, is there any hit on performance? I have read several times that orienting a GL view in anything other than the default portrait view will give a performance hit, although I can't find any solid evidence of this.
Thanks,
We think we have come up with a solution for this. We are doing two things, one for the keyboard and the other for the UITextView.
For the keyboard we are setting the status bar orientation. The keyboard follows when set.
[UIApplication sharedApplication].statusBarOrientation = UIInterfaceOrientationLandscapeRight;
And to get the UITextView to orient correctly we apply a transform to subviews of our EAGLView, which in this case is only the UITextView, as follows.
CGAffineTransform aTransform = CGAffineTransformMakeRotation(M_PI / 2);
[glView UpdateSubViewTransforms:aTransform];
This literally adds a 90 degree rotation to the view.
This has been tested on iPad & iPhone 4 with iOS 4.3, and on iPhone 3G with iOS 3.13.
I don't understand what's wrong in my very simple application with device rotation :
I built my view with interface builder. (See screen capture here)
I specified <key>UIInterfaceOrientation</key><string>UIInterfaceOrientationLandscapeRight</string> in my info.plist file.
I had a (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {return YES;} in my root view controller.
The area on the left (shown in red on the capture), around 20 pixel width, keeps inactive (nothing append if I hit a button in this area). In fact the full screen is active only in portrait mode, in landscape right mode there is this 20 pixels width inactive area, in landscape left mode this inactive area is on the right, in portrait upside down mode this area is on the bottom.
I read lots of posts and documentation about UIView rotation, but I did not find anything to solve this problem (I tried to play with view.frame and view.bounds without any success).
Anybody has an idea ?
Thanks a lot.
Regards.
Sébastien.
One of your views is probably not autoresized correctly.
After rotation, it still has its old bounds of, for example, 320 x 460. Since views normally don't clip their contained views you don't see a difference.
Events on the other hand are only delivered to views that are contained in their superviews bounds.
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.