UIStackView 和另一个 UIStackView 问题中的占位符视图

UIStackView and a placeholder view in another UIStackView problem

如果您在另一个 UIStackView(mainStack) 中有 UIStackView(testStack) 和占位符 UIView(testView),则会出现问题。意思是如果testStack里面没有内容就会崩溃,testView会把space全部拿走。甚至 testStackcontent hugging priority 设置为最大值,因此当没有子视图时它应该将其高度折叠为 0。但事实并非如此。如何让它在没有内容的时候崩溃?

PS 如果 testStack 中有项目,一切都按预期进行:testView 获取所有可用的 space,testStack 仅获取 space 以适应其子视图。

class AView: UIView {
    lazy var mainStack: UIStackView = {
        let stack = UIStackView()
        stack.axis = .vertical
        stack.backgroundColor = .gray
        stack.addArrangedSubview(self.testStack)
        stack.addArrangedSubview(self.testView)
        return stack
    }()
    
    let testStack: UIStackView = {
        let stack = UIStackView()
        stack.backgroundColor = .blue
        stack.setContentHuggingPriority(.init(1000), for: .vertical)
        return stack
    }()
    
    let testView: UIView = {
        let view = UIView()
        view.backgroundColor = .red
        return view
    }()
    
    init() {
        super.init(frame: .zero)
        backgroundColor = .yellow
        addSubview(mainStack)
        mainStack.translatesAutoresizingMaskIntoConstraints = false
        mainStack.topAnchor.constraint(equalTo: topAnchor).isActive = true
        mainStack.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        mainStack.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
        mainStack.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

当自动布局在 UIStackView 中排列子视图时,它会查看:

  • 堆栈视图的 .distribution 属性
  • 子视图的高度限制(如果给定)
  • 子视图的内部内容大小

由于您没有指定 .distribution 属性,mainStack 使用默认值 .fill

A UIStackView 具有 NO 内部内容大小,因此自动布局显示“testStack 的高度为零”

A UIView 具有 NO 内部内容大小,因此自动布局显示“testView 的高度为零”

由于分布是填充,自动布局有效地说:“排列的子视图的高度不明确,所以让我们给最后一个子视图一个零高度,然后填充mainStack 与第一个子视图。

设置 .setContentHuggingPriority 不会有任何效果,因为没有固有的高度可以“拥抱”。

如果您设置 mainStack 的 .distribution = .fillEqually,您将(如预期)testStack 填充上半部分,testView 填充下半部分。

如果你设置 mainStack 的 .distribution = .fillProportionally,你会得到相同的结果... testStack 填充上半部分,testView 填充下半部分,因为 .fillProportionally 使用排列的子视图的内部内容大小...在这种情况下,它们都是零,因此“比例”将相等。

如果您设置 mainStack 的 .distribution = .equalSpacing.distribution = .equalCentering,您将不会看到 testStacktestView ... 自动布局会给它们每个零的高度,并用(空)“间距”填充 mainStack 的其余部分。

如果您的目标是 testStack 在它为空时“消失”,您可以:

  • 将其隐藏,或者
  • 子类化并赋予其固有高度