【发布时间】:2018-02-25 10:52:53
【问题描述】:
我在 UIStackView 中排列子视图的布局时遇到问题,想知道是否有人可以帮助我了解发生了什么。
所以我有一些间距的 UIStackView(例如 1,但这没关系)和 .fillProportionally 分布。我正在添加仅具有 1x1 的 intrinsicContentSize 的排列子视图(可以是任何东西,只是方形视图),我需要它们在 stackView 中按比例拉伸。
问题是,如果我添加没有实际框架的视图,只有固有尺寸,那么我会得到这个错误的布局
否则,如果我添加具有相同大小框架的视图,一切都会按预期工作,
但我真的不喜欢设置视图的框架。
我很确定这完全是关于拥抱和抗压优先,但无法弄清楚正确答案是什么。
这是一个 Playground 示例:
import UIKit
import PlaygroundSupport
class LView: UIView {
// If comment this and leave only intrinsicContentSize - result is wrong
convenience init() {
self.init(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
}
// If comment this and leave only convenience init(), then everything works as expected
public override var intrinsicContentSize: CGSize {
return CGSize(width: 1, height: 1)
}
}
let container = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
container.backgroundColor = UIColor.white
let sv = UIStackView()
container.addSubview(sv)
sv.leftAnchor.constraint(equalTo: container.leftAnchor).isActive = true
sv.rightAnchor.constraint(equalTo: container.rightAnchor).isActive = true
sv.topAnchor.constraint(equalTo: container.topAnchor).isActive = true
sv.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true
sv.translatesAutoresizingMaskIntoConstraints = false
sv.spacing = 1
sv.distribution = .fillProportionally
// Adding arranged subviews to stackView, 24 elements with intrinsic size 1x1
for i in 0..<24 {
let a = LView()
a.backgroundColor = (i%2 == 0 ? UIColor.red : UIColor.blue)
sv.addArrangedSubview(a)
}
sv.layoutIfNeeded()
PlaygroundPage.current.liveView = container
【问题讨论】:
-
如果我运行您的确切代码,但将
.fillProportionally更改为.fillEqually,我会得到您的第二张图片...这就是您想要的吗? (顺便说一下,你的 for 循环中不需要sv.layoutIfNeeded()) -
.fillEqually 实际上并不是我想要的,因为我需要控制元素的宽度(在这个特定的水平示例中),并且 .fillEqually 将给出等宽的列。我的意思是,我确实需要一些列比其他列大两倍,例如,很少有其他列应该比两倍大的列大三倍。关于 sv.layoutIfNeeded(),你说得对,是我的错,在这个例子中我会把它移到循环之外。
-
如果你给循环内的每个视图添加一个宽度锚,会解决你的问题吗?
-
经过一些测试...当
.spacing不为零时,.fillProportionally似乎最终会得到奇怪的结果(更改为sv.spacing = 0,您将获得第二张图像,只是视图之间没有空格)。我不知道它是否会被视为“错误” - 或者只是一个“怪癖”。就好像自动布局正在对 spaces 应用按比例调整大小 --- 然后用绝对值渲染它们。 -
但是
width约束应该由UIStackView自动设置,不是吗?当您将视图添加为arrangedSubview时,width约束是根据添加视图的intrisicContentSize以及UIStackView中现有视图的数量和大小计算的,并应用于视图。为什么我需要再手动添加一次width约束?顺便说一句,如果我检查 View Debugging,最后一个宽度最大的元素将禁用width约束。这在我看来很奇怪。
标签: ios swift autolayout uistackview