带有 NSLayoutConstraints 的 UIView 灵活高度

Posted

技术标签:

【中文标题】带有 NSLayoutConstraints 的 UIView 灵活高度【英文标题】:UIView flexible height with NSLayoutConstraints 【发布时间】:2015-10-28 16:40:00 【问题描述】:

我在代码中向我的UIViewController 添加了一些视图,并使用NSLayoutConstraints 将它们定位在我希望它们在屏幕上的位置。在代码中对 NSLayoutConstraints 有点陌生;我做了一个测试设置,并且已经完成了 95%。这是我当前的代码:

UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:redView];

    [redView addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                        attribute:NSLayoutAttributeHeight
                                                        relatedBy:NSLayoutRelationEqual
                                                           toItem:nil attribute:0
                                                       multiplier:1
                                                         constant:100]];

    [redView addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                        attribute:NSLayoutAttributeWidth
                                                        relatedBy:NSLayoutRelationEqual
                                                           toItem:nil
                                                        attribute:0
                                                       multiplier:1
                                                         constant:693]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                          attribute:NSLayoutAttributeTop
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeTop
                                                         multiplier:1
                                                           constant:60]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1
                                                           constant:0]];


    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:blueView];
    [blueView addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                         attribute:NSLayoutAttributeHeight
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:nil
                                                         attribute:0
                                                        multiplier:10
                                                          constant:50]];

    [blueView addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                         attribute:NSLayoutAttributeWidth
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:nil attribute:0
                                                        multiplier:1
                                                          constant:693]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                          attribute:NSLayoutAttributeBottom
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:redView attribute:NSLayoutAttributeBottom
                                                         multiplier:1 constant:70]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:redView
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1
                                                           constant:0]];


    UIView *orangeView = [[UIView alloc] init];
    orangeView.backgroundColor = [UIColor orangeColor];
    orangeView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.view addSubview:orangeView];
    [orangeView addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                           attribute:NSLayoutAttributeHeight
                                                           relatedBy:NSLayoutRelationEqual
                                                              toItem:nil
                                                           attribute:0
                                                          multiplier:1
                                                            constant:25]];

    [orangeView addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                           attribute:NSLayoutAttributeWidth
                                                           relatedBy:NSLayoutRelationEqual
                                                              toItem:nil
                                                           attribute:0
                                                          multiplier:1
                                                            constant:693]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                          attribute:NSLayoutAttributeBottom
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:blueView
                                                          attribute:NSLayoutAttributeBottom
                                                         multiplier:1
                                                           constant:25]];

    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                          attribute:NSLayoutAttributeCenterX
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:blueView
                                                          attribute:NSLayoutAttributeCenterX
                                                         multiplier:1
                                                           constant:0]];

看起来像这样 - 正如我想要的那样:(忽略灰色背景 - 那是 superView)

现在我要做的是让orangeViews 的高度将屏幕的其余部分填充到superView 的底部。但是,当我向 orangeView 添加底部约束时,它也会调整其他视图的高度。

如何获得橙色视图高度以填充其下方的灰色区域?

编辑:

移除orangeView 上的高度约束并像这样向超级视图添加底部约束:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                          attribute:NSLayoutAttributeBottom
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:self.view
                                                          attribute:NSLayoutAttributeBottom
                                                         multiplier:1
                                                           constant:0]];

像这样改变视图:

【问题讨论】:

在将底部添加到超级视图约束时是否删除了橙色视图的高度约束? @Leonardo 是的,我试过了;查看我更新的问题,了解当我这样做时会发生什么。谢谢! 【参考方案1】:

您在橙色视图上设置了固定高度,那么它如何扩展并填充整个视图?

另外我建议您将视图的顶部固定到前一个视图的底部,因为您可以轻松更改视图大小并保持间距均匀,否则您将不得不调整底部的常量到底部的关系。

这是一个运行良好的代码:

UIView *redView = [[UIView alloc] init];
redView.backgroundColor = [UIColor redColor];
redView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addSubview:redView];

[redView addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                    attribute:NSLayoutAttributeHeight
                                                    relatedBy:NSLayoutRelationEqual
                                                       toItem:nil
                                                    attribute:0
                                                   multiplier:1
                                                     constant:100]];

[redView addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                    attribute:NSLayoutAttributeWidth
                                                    relatedBy:NSLayoutRelationEqual
                                                       toItem:nil
                                                    attribute:0
                                                   multiplier:1
                                                     constant:693]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                      attribute:NSLayoutAttributeTop
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self.view
                                                      attribute:NSLayoutAttributeTop
                                                     multiplier:1
                                                       constant:60]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:redView
                                                      attribute:NSLayoutAttributeCenterX
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self.view
                                                      attribute:NSLayoutAttributeCenterX
                                                     multiplier:1
                                                       constant:0]];


UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = [UIColor blueColor];
blueView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addSubview:blueView];
[blueView addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                     attribute:NSLayoutAttributeHeight
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:nil
                                                     attribute:0
                                                    multiplier:1
                                                      constant:50]];

[blueView addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                     attribute:NSLayoutAttributeWidth
                                                     relatedBy:NSLayoutRelationEqual
                                                        toItem:nil attribute:0
                                                    multiplier:1
                                                      constant:693]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                      attribute:NSLayoutAttributeTop
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:redView attribute:NSLayoutAttributeBottom
                                                     multiplier:1 constant:10]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:blueView
                                                      attribute:NSLayoutAttributeCenterX
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:redView
                                                      attribute:NSLayoutAttributeCenterX
                                                     multiplier:1
                                                       constant:0]];


UIView *orangeView = [[UIView alloc] init];
orangeView.backgroundColor = [UIColor orangeColor];
orangeView.translatesAutoresizingMaskIntoConstraints = NO;

[self.view addSubview:orangeView];

[orangeView addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                       attribute:NSLayoutAttributeWidth
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:nil
                                                       attribute:0
                                                      multiplier:1
                                                        constant:693]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                      attribute:NSLayoutAttributeTop
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:blueView
                                                      attribute:NSLayoutAttributeBottom
                                                     multiplier:1
                                                       constant:25]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                      attribute:NSLayoutAttributeBottom
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:self.view
                                                      attribute:NSLayoutAttributeBottom
                                                     multiplier:1
                                                       constant:0]];

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:orangeView
                                                      attribute:NSLayoutAttributeCenterX
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:blueView
                                                      attribute:NSLayoutAttributeCenterX
                                                     multiplier:1
                                                       constant:0]];

【讨论】:

这正是我所追求的。我最初试图将下一个视图固定在前一个视图的底部,除了我使用底部/底部关系而不是顶部/底部 - 没有完全理解代码。但现在我愿意。谢谢!【参考方案2】:

您需要将Y constraints 设置为橙色视图:为蓝色视图设置bottomLayout 约束和垂直间距。如果 XCode 用橙色警告警告您,请阅读这些警告,它通常会说“您的视图需要 X 约束”。

[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-[yourViewHere(300)]-50-|"
options:0
metrics:nil
views:NSDictionaryOfVariableBindings(yourViewHere)]];

(300) 是视图的宽度。该代码剪辑器将约束从 bottomLayout 设置为您的视图。如上所述添加类似的约束。

【讨论】:

以上是关于带有 NSLayoutConstraints 的 UIView 灵活高度的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSLayoutConstraints 调整当前视图的大小

在 UITableView 的标题视图上使用 NSLayoutConstraints

NSLayoutConstraints 的 UIViewPropertyAnimator 使视图消失

Swift 中的尾随和前导约束以编程方式 (NSLayoutConstraints)

Swift 中 NSLayoutConstraints 的奇怪行为

在 Swift 中枚举视图的 NSLayoutConstraints?