How to change or update NSLayoutConstraint programmatically

前提是你 提交于 2019-11-27 13:47:46

问题


I have implemented AutoLayout programmatically using the Code :

- (void)addConstraintWithListNavigationViewController:(UIView *)listViewNavigation y:(CGFloat)y height:(CGFloat)height
{
    //WIDTH_ListTableView = 0.4

    //set x = 0;
    NSLayoutConstraint *constraintToAnimate1 = [NSLayoutConstraint constraintWithItem:listViewNavigation
                                                                            attribute:NSLayoutAttributeLeft
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:self.view
                                                                            attribute:NSLayoutAttributeLeft
                                                                           multiplier:0.00
                                                                             constant:0];
    [self.view addConstraint:constraintToAnimate1];


    //set y = y;
    NSLayoutConstraint *constraintToAnimate2 = [NSLayoutConstraint constraintWithItem:listViewNavigation
                                                                            attribute:NSLayoutAttributeTop
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:self.view
                                                                            attribute:NSLayoutAttributeBottom
                                                                           multiplier:0.00
                                                                             constant:y];
    [self.view addConstraint:constraintToAnimate2];








    //set Width = self.view.frame.size.width*0.4
    NSLayoutConstraint *constraintToAnimate3 = [NSLayoutConstraint constraintWithItem:listViewNavigation
                                                                            attribute:NSLayoutAttributeWidth
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:self.view
                                                                            attribute:NSLayoutAttributeWidth
                                                                           multiplier:1-WIDTH_ListTableView
                                                                             constant:0.0];
    [self.view addConstraint:constraintToAnimate3];





    //Set height = height
    NSLayoutConstraint *constraintToAnimate4 = [NSLayoutConstraint constraintWithItem:listViewNavigation
                                                                            attribute:NSLayoutAttributeHeight
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:nil
                                                                            attribute:NSLayoutAttributeNotAnAttribute
                                                                           multiplier:0.00
                                                                             constant:height];
    [self.view addConstraint:constraintToAnimate4];
}

And this works perfect, but every-time this ViewController receives a Notification, it will run:

[self.view layoutIfNeeded];

But I want to set the width of listViewNavigation according a boolean variable connected.

if(connected){
        listViewNavigation.view.frame.size.width = 0.4 * self.view.frame.size.width;
    }
    else{
        listViewNavigation.view.frame.size.width = 0.6 * self.view.frame.size.width;
    }

But i do not know how can I update the NSLayoutConstraint :

NSLayoutConstraint *constraintToAnimate3 = [NSLayoutConstraint constraintWithItem:PreView
                                                                            attribute:NSLayoutAttributeWidth
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:self.view
                                                                            attribute:NSLayoutAttributeWidth
                                                                           multiplier:1 - WIDTH_ListTableView
                                                                             constant:0.0];
[self.view addConstraint:constraintToAnimate3];

when this ViewController receive the notification.


回答1:


I think you have 2 options.

Option 1 Keep a property

@property (strong,nonatomic)NSLayoutConstraint *constraintToAnimate3;

Then use this property to

self.constraintToAnimate3 = [NSLayoutConstraint constraintWithItem:PreView
                                                                        attribute:NSLayoutAttributeWidth
                                                                        relatedBy:NSLayoutRelationEqual
                                                                           toItem:self.view
                                                                        attribute:NSLayoutAttributeWidth
                                                                       multiplier:1
                                                                         constant:-1 * 0.4 * self.view.frame.size.width];
[self.view addConstraint:self.constraintToAnimate3];

When you want to change

if(connected){
    self.constraintToAnimate3.constant = -1 *0.6 * self.view.frame.size.width;
}
else{
    self.constraintToAnimate3.constant = -1 *0.4 * self.view.frame.size.width;
}
[UIView animateWithDuration:yourduration animations:^{
    [self.view layoutIfNeeded];
}];

Option 2 Set an identifier of constraintToAnimate3

constraintToAnimate3.identifier = @"1234"

Then search to get the constraint

NSLayoutConstraint * constraint3 = nil;
NSArray * constraints = self.view.constraints;
for (NSLayoutConstraint * constraint in constraints) {
    if ([constraint.identifier isEqualToString:@"1234"]) {
        constraint3 = constraint;
        break;
    }
}

Then change the constant as shown in Option1

Update: If use constant in the code I post

PreView.frame.size.with = self.view.size.width * multiplier + constant



回答2:


OK, I figure out.

[self.view removeConstraint:self.constraintOld];
[self.view addConstraint:self.constraintNew];

[UIView animateWithDuration:time animations:^{
    [self.view layoutIfNeeded];
}];



回答3:


It's essential that you don't just add the constraints to your view, but that you also remember them.

It's easiest to change a constraint if you only need to change its constant - the constant is the only part of a constraint that can be changed later repeatedly. To do that, you need to store the constraint on its own.

Otherwise you need to remove old constraints and add new ones. Since you usually have more than one constraint, store arrays with sets of constraints that may need to be replaced, then update the whole array. You can also use the activateConstraints and deactivateConstraints methods.



来源:https://stackoverflow.com/questions/30620016/how-to-change-or-update-nslayoutconstraint-programmatically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!