In "View Did Load" I'm trying to determine the size of the view so I can appropriately size a subview. I want it to always stretch about the length and width of the screen regardless of orientation.
quest *anview = [[quest alloc] initWithFrame: CGRectMake(50, 50, self.view.frame.size.width-100, self.view.frame.size.height-100)];
self.aquest=anview;
But this always returns a width of 748 and a height of 1024 when it should return the opposite when I'm in landscape. I know that you can't get orientation on the simulator but this occurs on the device as well. When I get the orientation:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
NSLog(#"device orientation:%d",orientation);
I correctly get the orientation but this log statement returns the 748/1024 regardless of orientation.
NSLog(#"size w:%f",self.view.frame.size.width);
NSLog(#"size h:%f",self.view.frame.size.height);
Anyone know what's going on? Does this have to do with me putting this in the viewdidLoad method? Should I put it in viewWillAppear or viewDidAppear?
Try to use the bounds property instead of frame.
The view is always created in portrait mode and then rotated, even if you launch the application in landscape. You should be able to keep the subview stretched by setting its size relative to the parent's portrait size and the autorsizing mask to UIViewAutoresizingMaskFlexibleWidth|UIViewAutoresizingFlexibleHeight, providing the shouldAutorotateToInterfaceOrientation: return YES for the right device orientation. It will also keep the distance from the top and left margin unless you add to the mask a different UIViewAutoresizingFlexibleMargin.
Related
On iOS 9.3 iPhones and iPads (actual devices and in the simulator), I am getting inconsistent information (between the device and the simulator) about the [UIScreen mainScreen].bounds after an orientation change notification.
My view controller adds a notification for orientation changes when the view loads:
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(deviceOrientationDidChangeNotification:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
The behaviour when the orientation changes is as follows:
- (void) deviceOrientationDidChangeNotification:(NSNotification *) notification {
CGRect frame = [UIScreen mainScreen].bounds;
NSLog(#"Main screen is w=%f h=%f", frame.size.width, frame.size.height);
}
Running this on an iPhone, after the orientation changes, the log message indicates a frame width and height that correspond with the post orientation change screen dimensions.
Running this on an iPad, after the orientation changes, the log message indicates a frame width and height that correspond with the pre orientation change screen dimensions.
Is this kind of inconsistency something that needs to be coded around? I could start trying to detect what the orientation is (landscape or portrait) and then using the width and height values that make sense but that is pretty hacky.
The right way to handle this is to avoid the notification system, instead using the
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator
method on the UIViewController where you want to adapt the UI for an orientation change.
In my app, some ViewControllers should be shown in fixed orientation but the others are free to rotate screen orientation. When I fix orientation on some ViewController using
NSNumber *value = [NSNumber NumberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
and this lock orientation well. However, when I back to previous ViewController or move to other ViewController which is free to rotate, orientation does not get back to real orientation.
I just release orientation lock when ViewController moves on, but [[UIDevice currentDevice] orientation] only returns value which I set value, not current device's real orientation. [UIViewController attemptRotationToDeviceOrientation] didn't work also.
How can I get current device's real orientation and refresh layout?
Thanks in advance.
I call:
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger: UIInterfaceOrientationLandscapeLeft]
forKey:#"orientation"];
And then I log out:
NSLog(#" = %#",NSStringFromCGRect(self.view.bounds));
And I get:
2015-04-06 11:04:13.02 [1032:262526] = {{0, 0}, {375, 667}}
This is on an iPhone 6. How come the bounds didn't change?
EDIT
So I saw in another answer that [UIScreen mainScreen].bounds gives the proper dimensions after setting rotation programmatically using setValue:forKey.
However, how come the view still has the portrait frame? Is this a delayed response? Do I have to rotate the view myself?
If you want to change interface orientation then you should look towards this callbacks
interfaceOrientation property
– shouldAutorotateToInterfaceOrientation:
+ attemptRotationToDeviceOrientation
– rotatingHeaderView
– rotatingFooterView
– willRotateToInterfaceOrientation:duration:
– willAnimateRotationToInterfaceOrientation:duration:
– didRotateFromInterfaceOrientation:
and I will suggest you to look towards this method too.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
Please refer this docs
adject your code inside this
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
if UIInterfaceOrientationLandscapeLeft{//code} else if UIInterfaceOrientationLandscapeRight{//code}
I'm developing an application in iOS8 in landscape mode and everything works fine. I'm using UIKit and don't support portrait mode at all.
Im trying to customise it to iOS7 but the frame that I'm getting is always like the iPhone is in a portrait mode.
I know that the in iOS8 there was a major change with the width and height and it's different in iOS7.
I have the following method which I used to set the window n the appDelegate and when I need the frame at the ViewControllers.
I'm doing the following:
- (CGRect) screenRect {
CGRect screenRect = [UIScreen mainScreen].bounds;
if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
return CGRectMake(0,0,screenRect.size.height, screenRect.size.width);
}
return screenRect;
}
The views look fine but the left/right side of the screen (depends on the device orientation) behaves like it's outside the frame. i.e doesn't response to gestures!
When I'm setting the fame to the new "screenRect" it keeps turning back to the device bounds.
Thank you very much.
This are getting me a little confuse. I know the 2 properties in UIScreen about the size screen, like in this question use applicationFrame, and this uses bounds.
applicationFrame - Show the size of device minus the statusBar. Making a NSLog in a iPhone, i get this values: (x=0, y=20, height= 460, width = 320)
bounds - Show all size screen. The values is: (x=0, y=0, height=480, width=320)
Now, if I rotate the device (potrait to ladscape) this will show
(The bounds will be all the same value)
Go to function: shouldAutorotateToInterfaceOrientation: x= 0 y=20 height= 460 width= 320
return YES so
Go function: didRotateFromInterfaceOrientation: x= 20 y=0 height= 480 width= 300
I don't know why, but this pass one more time in shouldAutorotateToInterfaceOrientation and show: x= 20 y=0 height= 480 width= 300 (Is this a bug?)
I want to resize my view to this new size, but if I get the CGRect, it will give the correct size in the didRotateFromInterfaceOrientation and the height will be width and vice-versa.
Are there a good way to beautiful resize my view without setting this values by hand?
(Assuming this point was for rotating from landscape back to portrait)
I don't know why, but this pass one
more time in
shouldAutorotateToInterfaceOrientation
and show: x= 20 y=0 height= 480 width=
300 (Is this a bug?)
Its not a bug!
shouldAutorotateToInterfaceOrientation is called before the UI rotates to match the orientation of the device. So, in the first case (Portrait to Landscape) it gives you the rect for the portrait orientation. in the second case (Landscape to Portrait) it gives you the rect for the Landscape orientation.
Bottomline:
shouldAutorotateToInterfaceOrientation gives CGRect values before initiating the UI rotation
didRotateFromInterfaceOrientation gives CGRect values after completing the UI rotation
I suggest you look autoresizesSubviews and autoresizingMask properties of UIView. This saves a lot of headaches when you are working with views that have to rotate/resize.
Hope I have answered your question and you find this useful!