Is it possible to change autolayout constraints during runtime?
I know you can change the constant, but how would you change different attributes.
For example, NSLayoutAttributeTop to NSLayoutAttributeBottom?
Here is a simple sample of what I hope to achieve, it will set a label top left, then when you press a button it will set the label bottom right.
The initial constraints work as expected, tapping the button doesn't work as expected and throws the infamous "Unable to simultaneously satisfy constraints."
Here is the code I am using:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
self.constraintA = [NSLayoutConstraint constraintWithItem:self.topLabel
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0];
self.constraintB = [NSLayoutConstraint constraintWithItem:self.topLabel
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0.0];
[self.view addConstraint:self.constraintA];
[self.view addConstraint:self.constraintB];
}
- (IBAction)tappedChange:(id)sender
{
[self.view removeConstraints:@[ self.constraintA, self.constraintB ]];
self.constraintA = [NSLayoutConstraint constraintWithItem:self.topLabel
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0.0];
self.constraintB = [NSLayoutConstraint constraintWithItem:self.topLabel
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0.0];
[self.view addConstraint:self.constraintA];
[self.view addConstraint:self.constraintB];
[self.view setNeedsLayout];
}
Thank you for your time.
You only need to perform the Remove/Recreate/Add constraint dance on iOS 7 and below. If you are writing for a modern iOS (8 and above) you can create all your constraints at once and then just set the .active
property on whatever NSLayoutConstraint
instance you want at any given time.
// Move to right
self.leadingConstraint.active = false;
self.trailingConstraint.active = true;
// Move to bottom
self.topConstraint.active = false;
self.bottomConstraint.active = true;
If you are using Interface Builder you can create all the constraints that will be needed (note the grayed out constraints that aren't active by default).
Then when the button is pressed you can deactivate the old constraints and activate the new ones.
If you are ever unsure about the views being shown you can pause the app execution and use the following private API in the debugger to print out a full list of views and constraints:
po [[UIWindow keyWindow] _autolayoutTrace]
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