I want to modify the layout constraints when the device rotates.
My UIViewController
is composed of 2 UIViews
, in landscape they are horizontally aligned,
and in portrait they are vertically aligned.
It does work actually, in willAnimateRotationToInterfaceOrientation
, I remove the desired constraints and replaced them with others to have the right layout...
But there are problems, during rotation auto layout starts breaking constraints before willAnimateRotationToInterfaceOrientation
is called, so where are we meant to replace our constraints when the device reorientation occurs ?
Another issue is performance, after a few rotations the system doesn't break anymore constraints, but I have a huge performance drop, especially in portrait mode...
There is very good explanation of auto-layout and rotations in Matthijs Hollemans post. You can find it here: http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2
Usually, you need about 4 constraints to correctly position your view. If my views have constant size i prefer to pin height and width. After that you can use Leading and Top space constraints to do whatever you want. For example, you can set IBOutlets for leading and top space constraints for your views:
@interface ViewController : UIViewController {
IBOutlet NSLayoutConstraint *_leadingSpaceConstraint;
IBOutlet NSLayoutConstraint *_topSpaceConstraint;
}
Then control-drag from outlet to your constraint. Now you can directly change your view constraint from code:
_leadingSpaceConstraint.constant = NEW_CONSTRAINT_VALUE;
To commit your changes you need to call:
[self.view layoutIfNeeded];
And if you want to do it animated:
[UIView animateWithDuration:0.25
animations:^{
[self.view layoutIfNeeded];
}];
I think it will work in willAnimateRotationToInterfaceOrientation, because you don't need to break any constraints with this approach.
Some example: You have two square view in portrait orientation, one under another. Set their "leading space to superview" constraints to 20, for example. Then set "top space to superview constraint" to 20 for first view and to 120 for second. It will be our default setup.
Then, after rotation you need to recalculate your constraints. Now set both of top constraints to 20, and leading constraints to 20 and 120 respectively. Then commit changes with layoutIfNeeded.
I hope it will help.
In willRotateToInterfaceOrientation:duration:
, send setNeedsUpdateConstraints
to any view that needs its constraints modified.
Alternatively, make a UIView
subclass. In your subclass, register to receive UIApplicationWillChangeStatusBarOrientationNotification
. When you receive the notification, send yourself setNeedsUpdateConstraints
.
This sets the needsUpdateConstraints
flag on the view. Before the system performs layout (by sending layoutSubviews
messages), it sends an updateConstraints
message to any view that has the needsUpdateConstraints
flag set. This is where you should modify your constraints. Make a UIView
subclass and override updateConstraints
to update your constraints.
override -(void) viewWillLayoutSubviews
in your UIViewController
to update your constraints as below code:
-(void) viewWillLayoutSubviews {
switch(self.interfaceorientation)
{
case UIInterfaceOrientationLandscapeLeft:
break;
case UIInterfaceOrientationLandscapeRight:
break;
case UIDeviceOrientationPortrait:
break;
case UIDeviceOrientationPortraitUpsideDown:
break;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With