在运行时更改Autolayout

时间:2015-11-12 22:48:35

标签: ios objective-c autolayout

是否可以在运行时更改自动布局约束?

我知道您可以更改常量,但是如何更改不同的属性。

例如,NSLayoutAttributeTop到NSLayoutAttributeBottom?

以下是我希望实现的简单示例,它将在左上方设置标签,然后当您按下按钮时,它会将标签设置在右下方。

初始约束按预期工作,点击按钮不会按预期工作,并抛出臭名昭着的“无法同时满足约束。”#34;

以下是我正在使用的代码:

    - (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];
}

感谢您的时间。

2 个答案:

答案 0 :(得分:6)

您只需要在iOS 7及更低版本上执行删除/重新创建/添加约束舞蹈。如果您正在为现代iOS(8及以上版本)编写代码,则可以立即创建所有约束,然后在任何给定时间将.active属性设置为您想要的任何NSLayoutConstraint实例。

// Move to right
self.leadingConstraint.active = false;
self.trailingConstraint.active = true;

// Move to bottom
self.topConstraint.active = false;
self.bottomConstraint.active = true;

如果您使用的是Interface Builder,则可以创建所有所需的约束(请注意默认情况下不活动的灰色约束)。

Xcode Window Showing Example

然后按下按钮时,您可以取消激活旧约束并激活新约束。

如果您不确定要显示的视图,可以暂停应用程序执行并在调试器中使用以下私有API打印出完整的视图和约束列表:

po [[UIWindow keyWindow] _autolayoutTrace]

答案 1 :(得分:0)

就我个人而言,我喜欢使用Masonry来管理代码中的约束 - 它的写作方式更少,更容易阅读六个月前写的内容,而学习曲线并不像头部分裂那样任

例如:

// Define some constraints, making the top one a @property:
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    self.topConstraint = make.top.equalTo(superview.mas_top).with.offset(padding.top);
    make.left.equalTo(superview.mas_left).with.offset(padding.left);
}];

// Update the top constraint to match the bottom of the superview instead of the top
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    self.topConstraint = make.top.equalTo(superview.mas_bottom).with.offset(padding.bottom);
}];