不同 UIStackView 的子视图之间的等高约束

Posted

技术标签:

【中文标题】不同 UIStackView 的子视图之间的等高约束【英文标题】:Equal Height constraints between different UIStackView's subviews 【发布时间】:2020-02-19 13:23:45 【问题描述】:

我有一个约束场景,它在通过界面构建​​器构建时可以完美运行,但我无法通过代码实现。屏幕布局如下:

一个水平的UIStackView 与多个垂直的UIStackView 内联。这些垂直的UIStackView 中的每一个在其中都有多个UIView。我想要实现的是:inline UIView with equal height

通过界面生成器创建此类约束时,它可以完美运行:

但是通过代码创建此约束时,我遇到以下错误:

'Unable to activate constraint with anchors <NSLayoutDimension:0x600002b9a6c0 "UIView:0x7f9e6f075c30.height"> and <NSLayoutDimension:0x600002b9a700 "UIView:0x7f9e6c423d50.height"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

我尝试使用以下方式创建这些约束:

1.

let heightConstraint = NSLayoutConstraint(item: view1,
                                          attribute: .height,
                                          relatedBy: .equal,
                                          toItem: view2,
                                          attribute: .height,
                                          multiplier: 1,
                                          constant: 0)
NSLayoutConstraint.activate([heightConstraint])

2.

let heightConstraint = NSLayoutConstraint(item: view1,
                                          attribute: .height,
                                          relatedBy: .equal,
                                          toItem: view2,
                                          attribute: .height,
                                          multiplier: 1,
                                          constant: 0)
horizontalStackView.addConstraint(heightConstraint)

其中horizontalStackView 是包含所有垂直堆栈视图的水平堆栈视图。

我不知道在哪里添加了这些约束,以便通过界面生成器通过代码创建它们。

【问题讨论】:

您是否也使用代码创建了 UI 元素? @PGDev 是的,它们也是通过代码创建的 然后添加代码。 好的,等我写完 你也试过horizontalStackView.heightAnchor.constraint(equalToConstant: 0).isActive = true吗? 【参考方案1】:

以下是使用代码获取上述 UI 的方法,

1.用相关的backgroundColors创建UIView's

    let v1 = UIView()
    v1.backgroundColor = #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)
    v1.translatesAutoresizingMaskIntoConstraints = false

    let v2 = UIView()
    v2.backgroundColor = #colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1)
    v2.translatesAutoresizingMaskIntoConstraints = false

    let v3 = UIView()
    v3.backgroundColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
    v3.translatesAutoresizingMaskIntoConstraints = false

    let v4 = UIView()
    v4.backgroundColor = #colorLiteral(red: 0.5058823824, green: 0.3372549117, blue: 0.06666667014, alpha: 1)
    v4.translatesAutoresizingMaskIntoConstraints = false

    let v5 = UIView()
    v5.backgroundColor = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)
    v5.translatesAutoresizingMaskIntoConstraints = false

    let v6 = UIView()
    v6.backgroundColor = #colorLiteral(red: 0.9686274529, green: 0.78039217, blue: 0.3450980484, alpha: 1)
    v6.translatesAutoresizingMaskIntoConstraints = false

    let v7 = UIView()
    v7.backgroundColor = #colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)
    v7.translatesAutoresizingMaskIntoConstraints = false

    let v8 = UIView()
    v8.backgroundColor = #colorLiteral(red: 0.9372549057, green: 0.3490196168, blue: 0.1921568662, alpha: 1)
    v8.translatesAutoresizingMaskIntoConstraints = false

    let v9 = UIView()
    v9.backgroundColor = #colorLiteral(red: 0.06274510175, green: 0, blue: 0.1921568662, alpha: 1)
    v9.translatesAutoresizingMaskIntoConstraints = false

2. 使用上面创建的UIViews 创建horizontalStackViews。不要忘记将 distribution 设置为 fillEqually

    let hStack1 = UIStackView(arrangedSubviews: [v1, v2, v3])
    hStack1.axis = .horizontal
    hStack1.distribution = .fillEqually
    hStack1.translatesAutoresizingMaskIntoConstraints = false

    let hStack2 = UIStackView(arrangedSubviews: [v4, v5, v6])
    hStack2.axis = .horizontal
    hStack2.distribution = .fillEqually
    hStack2.translatesAutoresizingMaskIntoConstraints = false

    let hStack3 = UIStackView(arrangedSubviews: [v7, v8, v9])
    hStack3.axis = .horizontal
    hStack3.distribution = .fillEqually
    hStack3.translatesAutoresizingMaskIntoConstraints = false

3. 使用上面创建的horizontalStackViews 创建verticalStackView 并将其distribution 设置为fillEqually 为好

    let vStack = UIStackView(arrangedSubviews: [hStack1, hStack2, hStack3])
    vStack.axis = .vertical
    vStack.distribution = .fillEqually
    vStack.translatesAutoresizingMaskIntoConstraints = false

4.添加vStackcontroller'sview

    self.view.addSubview(vStack)

5.将下面的constraints添加到vStack

    vStack.heightAnchor.constraint(equalToConstant: 200).isActive = true
    vStack.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    vStack.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    vStack.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

截图:

【讨论】:

【参考方案2】:

您应该关注“因为他们没有共同的祖先”部分。该问题可能与您的视图未添加到同一个容器视图有关。

我不知道您是如何创建视图的,但在某些时候您需要执行self.addSubview(yourView) 之类的操作,这将解决您的问题。

【讨论】:

以上是关于不同 UIStackView 的子视图之间的等高约束的主要内容,如果未能解决你的问题,请参考以下文章

即使隐藏了排列的子视图,UIStackView 似乎也会堆叠间距

为啥 UIStackView 调整排列的子视图的大小?

为啥 UIStackView 不堆叠 UILabel 安排的子视图?

相对于堆栈视图高度约束 UIStackView 的子视图

如何在 Xcode 中调整 UIStackView 的子视图大小?

当轴垂直时在 UIStackView 的子视图上设置恒定宽度