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

Posted

技术标签:

【中文标题】为啥 UIStackView 不堆叠 UILabel 安排的子视图?【英文标题】:Why does UIStackView not stack a UILabel arrangedSubview?为什么 UIStackView 不堆叠 UILabel 安排的子视图? 【发布时间】:2018-03-30 19:45:18 【问题描述】:

我有一个 UIStackView,作为排列的子视图,我有两个 UIView 和一个 UILabel。 UIView 一个接一个堆叠,而 UILabel 与子视图的前沿对齐。

代码:

let stack = UIStackView()
stack.axis = .horizontal
stack.distribution = .fillProportionally
stack.alignment = .center
stack.spacing = 7
view.addSubview(stack)
stack.translatesAutoresizingMaskIntoConstraints = false
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

let icon = UIView()
icon.backgroundColor = UIColor.red
stack.addArrangedSubview(icon)
icon.translatesAutoresizingMaskIntoConstraints = false
icon.heightAnchor.constraint(equalToConstant: 42).isActive = true
icon.widthAnchor.constraint(equalToConstant: 42).isActive = true

let icon2 = UIView()
icon2.backgroundColor = UIColor.red
stack.addArrangedSubview(icon2)
icon2.translatesAutoresizingMaskIntoConstraints = false
icon2.heightAnchor.constraint(equalToConstant: 42).isActive = true
icon2.widthAnchor.constraint(equalToConstant: 42).isActive = true

let label = UILabel()
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.sizeToFit()
label.translatesAutoresizingMaskIntoConstraints = false
label.backgroundColor = .yellow
label.text = "Hello World! Again"
label.textColor = .black
stack.addArrangedSubview(label)

输出:

【问题讨论】:

多行标签没有固有宽度(嗯,确实有,但不是您尝试使用它的方式)。你必须以某种方式给它一个宽度,要么通过约束,要么通过约束其容器的宽度——在这种情况下,是堆栈视图的宽度。 【参考方案1】:

为了清楚起见...

首先,不要使用.fillProportionally。无论你认为这会做什么,它都是错误的。您已将两个“图标”明确设置为每个 42 点宽。如果堆栈视图使用.fillProportionally,它将尝试更改这些视图的宽度,您将遇到自动布局冲突。

其次,UILabel.numberOfLines = 0 必须有宽度。否则,没有办法知道在哪里打断文本......如果有很多文本,它会延伸到视图的两侧。

第三,label.sizeToFit() 行在这里不会完成任何事情。删掉就好了。

如果添加这一行:

stack.widthAnchor.constraint(equalToConstant: 200.0).isActive = true

然后堆栈视图将扩展到 200 点宽...

自动布局将使第一个排列视图的宽度为 42(因为这是您声明的宽度),第二个视图也是如此。由于您已将间距设置为7,因此它将计算

42 + 7 + 42 + 7

等于98。它从堆栈视图的宽度中减去它:

200 - 98 = 102

是它会给你的标签的宽度。

结果:

如果您不想将宽度显式设置为200,则可以将其设置为父视图宽度的百分比,或为其设置前导和尾随约束。

【讨论】:

【参考方案2】:

尝试将distribution改为fill

stack.distribution = .fill

多行设置

评论后

【讨论】:

所以确实将它放入堆栈(耶),但它不尊重 uilabel 的固有大小,即它压扁它,使其与其他两个 UIView 的宽度相同,并且导致文本在几乎每个单词后中断。 让它拉伸评论 .lines ,或者给它一个宽度

以上是关于为啥 UIStackView 不堆叠 UILabel 安排的子视图?的主要内容,如果未能解决你的问题,请参考以下文章

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

缩小 UIStackView 子项

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

为啥图像视图会拉伸以填充 UIStackView 中宽度的一半?

解决 UIStackView 布局歧义

为啥父 UIStackView 无法识别子 StackView 的高度?