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

Posted

技术标签:

【中文标题】UIStackView 和另一个 UIStackView 问题中的占位符视图【英文标题】:UIStackView and a placeholder view in another UIStackView problem 【发布时间】:2021-01-15 10:31:38 【问题描述】:

如果您在另一个UIStackView(mainStack) 中有一个UIStackView(testStack) 和一个占位符UIView(testView),则会出现问题。这意味着如果testStack 中没有内容,它将崩溃,testView 将占用所有空间。甚至将content hugging priority 设置为testStack 的最大值,因此当没有子视图时它应该将其高度折叠为0。但事实并非如此。没有内容时如何让它崩溃?

PS 如果testStack 中有项目,一切都会按预期进行:testView 占用所有可用空间,testStack 仅占用空间以适应其子视图。

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")
    

【问题讨论】:

当你将AView 的实例添加到你的主视图时,你是否给它一个高度约束? @DonMag 我使它成为超级视图的边缘,这基本上赋予了它高度 【参考方案1】:

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

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

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

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

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

由于分布是填充,自动布局有效地表示:“排列的子视图的高度是不明确的,所以让我们将最后一个子视图的高度设为零,并用第一个子视图填充 mainStack .

设置.setContentHuggingPriority 将不起作用,因为“拥抱”没有内在的高度。

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

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

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

如果您的目标是让testStack“消失”(如果它为空),您可以:

将其设置为隐藏,或 对其进行子类化并赋予其固有高度

【讨论】:

以上是关于UIStackView 和另一个 UIStackView 问题中的占位符视图的主要内容,如果未能解决你的问题,请参考以下文章

从 UIStackView 中缺少的代码添加的 UITextView

垂直分布两个水平按钮行

Swift - ScrollView 中的 StackView 不滚动

iOS/Swift:UITableViewCell 中的两个嵌入式视图在运行时未出现

拉伸 UIStackView 中的最后一个元素

UIStackView 嵌入在 UIStackView 对齐中