为什么具有单个视图、按比例填充和布局边距的 UIStackView 会导致模糊约束错误?
Why does a UIStackView with a single view, fill Proportionally, and Layout Margins causes ambiguous constraint error?
以下代码尝试将 UIStackView 添加到视图控制器,固定在所有边上并留有一点边距,并向其添加标签。
我希望 StackView 使用 .fillProportionally
作为它的分发模式,以备我稍后向其中添加更多视图时使用。
似乎对于单个排列的子视图只要分布模式是.fillProportionally
和layout使用 margins 然后我得到一个不明确的约束错误(如下)。这个错误的原因是什么?
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: .zero)
label.text = "ABC"
let stack = UIStackView(arrangedSubviews: [label])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.distribution = .fillProportionally
stack.isLayoutMarginsRelativeArrangement = true
stack.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10)
view.addSubview(stack)
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.widthAnchor.constraint(equalTo: view.widthAnchor),
stack.heightAnchor.constraint(equalTo: view.heightAnchor),
])
}
}
模糊约束错误(WTFAutoLayout):
(
"<NSLayoutConstraint:0x600001a432f0 'UISV-canvas-connection' UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'.leading == UILabel:0x7ff470913280'ABC'.leading (active)>",
"<NSLayoutConstraint:0x600001a423f0 'UISV-canvas-connection' UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'.trailing == UILabel:0x7ff470913280'ABC'.trailing (active)>",
"<NSLayoutConstraint:0x600001a425d0 'UISV-fill-proportionally' UILabel:0x7ff470913280'ABC'.width == UIStackView:0x7ff46d510030.width (active)>",
"<NSLayoutConstraint:0x600001a77f70 'UIView-leftMargin-guide-constraint' H:|-(10)-[UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7ff46d510030 )>",
"<NSLayoutConstraint:0x600001a42940 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide']-(10)-|(LTR) (active, names: '|':UIStackView:0x7ff46d510030 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600001a423f0 'UISV-canvas-connection' UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'.trailing == UILabel:0x7ff470913280'ABC'.trailing (active)>
首先,将label
的translatesAutoresizingMaskIntoConstraints
设为false
。
label.translatesAutoresizingMaskIntoConstraints = false
由于要将layoutMargins
全部设为10
,所以stack
的width
和height
不能等于view's
width
和 height
。
您需要在 width
和 height
中容纳 20(双方)的差异。
所以 constraints
应该是,
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1, constant: -20),
stack.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1, constant: -20),
])
另外,margin spacing包含在constraints之内,不需要写下面的代码。所以删除它。
stack.isLayoutMarginsRelativeArrangement = true
stack.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10)
编辑澄清,因为我原来的答案并不完全正确...
首先,UIStackView
的 .fillProportionally
分布 属性 经常被误解。
其次,当堆栈视图的分布 .fillProportionally
和 堆栈视图的 .spacing
不是 0
,或者当堆栈视图 也 设置了 .layoutMargins
时。
您遇到的问题是自动布局计算比例大小的方式。
根据实验,自动布局计算视图的比例宽度,然后然后应用布局边距,减去从最后一个视图的宽度来容纳space.
这可以很容易地证明如下:
有 6 个水平堆栈视图,每个设置为 200 点宽,分布设置为 .fillProportionally
,并填充一个或两个视图。红色视图的固有宽度为 25,绿色视图为 75。
第一个堆栈视图,具有单个视图且没有布局边距,按预期填充宽度...红色视图占据 100% space。
第二个堆栈视图,有两个视图,没有布局边距,也按预期填充...红色视图为 50 磅宽 (25%),绿色视图为 150 磅宽 (75%) .
但是,第三个堆栈视图开始显示问题。单个视图的比例宽度为 100%,或 200 点……但随后应用了布局边距。这会将视图从左侧移动 10 磅,但是因为自动布局不会从 first 子视图中减去 space,所以它实际上超出了 10 磅的边缘堆栈视图(所以红色视图是 仍然 200 点宽)。
第四个堆栈视图看起来就像它在做我们想要的......每侧边距为 10 磅的比例填充......红色视图为 50 磅宽(200 的 25%)但是 绿色视图只有 130 点宽。所以自动布局给两个视图 50 点 (25%) 和 150 点 (75%) 但是 然后它应用边距 和离开绿色视图 20 分。
为底部的两个堆栈视图使用 left: 100 right: 0
或 left: 0 right: 100
的布局边距使其更加明显。同样,对于其中的每一个,红色获得 50 分 (25%),绿色获得 150 分 (75%),但是随后 100 分的余量从绿色中剥离。
所以,要回答最初的问题,即当我们只有一个排列的子视图 and 布局边距时,为什么我们会得到不明确的约束,看在堆栈视图 3. 自动布局无法给红色 100% 的 space and 应用边距,所以它抛出布局错误。
这是 运行 上述示例的代码。如果您注释掉第三个堆栈视图,您不会得到错误:
class ProportionalStackExampleViewController: UIViewController {
let outerStackView: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = false
v.axis = .vertical
v.spacing = 8
return v
}()
let outerStackFrame: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.layer.borderWidth = 0.5
v.layer.borderColor = UIColor.blue.cgColor
return v
}()
let infoLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.font = UIFont.systemFont(ofSize: 12.0, weight: .light)
v.numberOfLines = 0
v.textAlignment = .center
v.text = "Red views have intrinsic width of 25\nGreen views have intrinsic width of 75\nAll horizontal stack views are 200-pts wide\nTap any view to see its width"
return v
}()
let sizeLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = "(width)"
return v
}()
let myGreen = UIColor(red: 0, green: 0.75, blue: 0, alpha: 1.0)
override func viewDidLoad() {
super.viewDidLoad()
for _ in 1...6 {
let lbl = UILabel()
lbl.font = UIFont.systemFont(ofSize: 12.0, weight: .light)
lbl.numberOfLines = 0
lbl.textAlignment = .center
outerStackView.addArrangedSubview(lbl)
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .horizontal
sv.distribution = .fillProportionally
sv.spacing = 0
outerStackView.addArrangedSubview(sv)
}
view.addSubview(infoLabel)
view.addSubview(sizeLabel)
view.addSubview(outerStackFrame)
view.addSubview(outerStackView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
infoLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
infoLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
infoLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
sizeLabel.topAnchor.constraint(equalTo: infoLabel.bottomAnchor, constant: 20.0),
sizeLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
outerStackView.topAnchor.constraint(equalTo: sizeLabel.bottomAnchor, constant: 20.0),
outerStackView.widthAnchor.constraint(equalToConstant: 200.0),
outerStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
outerStackFrame.widthAnchor.constraint(equalTo: outerStackView.widthAnchor),
outerStackFrame.heightAnchor.constraint(equalTo: outerStackView.heightAnchor),
outerStackFrame.centerXAnchor.constraint(equalTo: outerStackView.centerXAnchor),
outerStackFrame.centerYAnchor.constraint(equalTo: outerStackView.centerYAnchor),
])
// StackView 1
if let lbl = outerStackView.arrangedSubviews[0] as? UILabel,
let sv = outerStackView.arrangedSubviews[1] as? UIStackView {
lbl.text = "One view, no layoutMargins"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 2
if let lbl = outerStackView.arrangedSubviews[2] as? UILabel,
let sv = outerStackView.arrangedSubviews[3] as? UIStackView {
lbl.text = "Two views, no layoutMargins"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// comment out this block to see the auto-layout error goes away
// StackView 3
if let lbl = outerStackView.arrangedSubviews[4] as? UILabel,
let sv = outerStackView.arrangedSubviews[5] as? UIStackView {
lbl.text = "One view\nlayoutMargins left: 10 right: 10"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 10, bottom: 0, right: 10)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 4
if let lbl = outerStackView.arrangedSubviews[6] as? UILabel,
let sv = outerStackView.arrangedSubviews[7] as? UIStackView {
lbl.text = "Two views\nlayoutMargins left: 10 right: 10"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 10, bottom: 0, right: 10)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 5
if let lbl = outerStackView.arrangedSubviews[8] as? UILabel,
let sv = outerStackView.arrangedSubviews[9] as? UIStackView {
lbl.text = "layoutMargins left: 100 right: 0"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 100, bottom: 0, right: 0)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 6
if let lbl = outerStackView.arrangedSubviews[10] as? UILabel,
let sv = outerStackView.arrangedSubviews[11] as? UIStackView {
lbl.text = "layoutMargins left: 0 right: 100"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 0, bottom: 0, right: 100)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
}
@objc func showWidth(_ sender: UITapGestureRecognizer) -> Void {
if let v = sender.view {
sizeLabel.text = "Width: \(v.frame.width)"
sizeLabel.textColor = v.backgroundColor
}
}
}
class ProportionalView: UIView {
var w: CGFloat = 1.0
override var intrinsicContentSize: CGSize {
return CGSize(width: w, height: 40.0)
}
}
以下代码尝试将 UIStackView 添加到视图控制器,固定在所有边上并留有一点边距,并向其添加标签。
我希望 StackView 使用 .fillProportionally
作为它的分发模式,以备我稍后向其中添加更多视图时使用。
似乎对于单个排列的子视图只要分布模式是.fillProportionally
和layout使用 margins 然后我得到一个不明确的约束错误(如下)。这个错误的原因是什么?
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: .zero)
label.text = "ABC"
let stack = UIStackView(arrangedSubviews: [label])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.distribution = .fillProportionally
stack.isLayoutMarginsRelativeArrangement = true
stack.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10)
view.addSubview(stack)
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.widthAnchor.constraint(equalTo: view.widthAnchor),
stack.heightAnchor.constraint(equalTo: view.heightAnchor),
])
}
}
模糊约束错误(WTFAutoLayout):
(
"<NSLayoutConstraint:0x600001a432f0 'UISV-canvas-connection' UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'.leading == UILabel:0x7ff470913280'ABC'.leading (active)>",
"<NSLayoutConstraint:0x600001a423f0 'UISV-canvas-connection' UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'.trailing == UILabel:0x7ff470913280'ABC'.trailing (active)>",
"<NSLayoutConstraint:0x600001a425d0 'UISV-fill-proportionally' UILabel:0x7ff470913280'ABC'.width == UIStackView:0x7ff46d510030.width (active)>",
"<NSLayoutConstraint:0x600001a77f70 'UIView-leftMargin-guide-constraint' H:|-(10)-[UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'](LTR) (active, names: '|':UIStackView:0x7ff46d510030 )>",
"<NSLayoutConstraint:0x600001a42940 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide']-(10)-|(LTR) (active, names: '|':UIStackView:0x7ff46d510030 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600001a423f0 'UISV-canvas-connection' UILayoutGuide:0x6000000f3100'UIViewLayoutMarginsGuide'.trailing == UILabel:0x7ff470913280'ABC'.trailing (active)>
首先,将label
的translatesAutoresizingMaskIntoConstraints
设为false
。
label.translatesAutoresizingMaskIntoConstraints = false
由于要将layoutMargins
全部设为10
,所以stack
的width
和height
不能等于view's
width
和 height
。
您需要在 width
和 height
中容纳 20(双方)的差异。
所以 constraints
应该是,
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1, constant: -20),
stack.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 1, constant: -20),
])
另外,margin spacing包含在constraints之内,不需要写下面的代码。所以删除它。
stack.isLayoutMarginsRelativeArrangement = true
stack.layoutMargins = .init(top: 10, left: 10, bottom: 10, right: 10)
编辑澄清,因为我原来的答案并不完全正确...
首先,UIStackView
的 .fillProportionally
分布 属性 经常被误解。
其次,当堆栈视图的分布 .fillProportionally
和 堆栈视图的 .spacing
不是 0
,或者当堆栈视图 也 设置了 .layoutMargins
时。
您遇到的问题是自动布局计算比例大小的方式。
根据实验,自动布局计算视图的比例宽度,然后然后应用布局边距,减去从最后一个视图的宽度来容纳space.
这可以很容易地证明如下:
有 6 个水平堆栈视图,每个设置为 200 点宽,分布设置为 .fillProportionally
,并填充一个或两个视图。红色视图的固有宽度为 25,绿色视图为 75。
第一个堆栈视图,具有单个视图且没有布局边距,按预期填充宽度...红色视图占据 100% space。
第二个堆栈视图,有两个视图,没有布局边距,也按预期填充...红色视图为 50 磅宽 (25%),绿色视图为 150 磅宽 (75%) .
但是,第三个堆栈视图开始显示问题。单个视图的比例宽度为 100%,或 200 点……但随后应用了布局边距。这会将视图从左侧移动 10 磅,但是因为自动布局不会从 first 子视图中减去 space,所以它实际上超出了 10 磅的边缘堆栈视图(所以红色视图是 仍然 200 点宽)。
第四个堆栈视图看起来就像它在做我们想要的......每侧边距为 10 磅的比例填充......红色视图为 50 磅宽(200 的 25%)但是 绿色视图只有 130 点宽。所以自动布局给两个视图 50 点 (25%) 和 150 点 (75%) 但是 然后它应用边距 和离开绿色视图 20 分。
为底部的两个堆栈视图使用 left: 100 right: 0
或 left: 0 right: 100
的布局边距使其更加明显。同样,对于其中的每一个,红色获得 50 分 (25%),绿色获得 150 分 (75%),但是随后 100 分的余量从绿色中剥离。
所以,要回答最初的问题,即当我们只有一个排列的子视图 and 布局边距时,为什么我们会得到不明确的约束,看在堆栈视图 3. 自动布局无法给红色 100% 的 space and 应用边距,所以它抛出布局错误。
这是 运行 上述示例的代码。如果您注释掉第三个堆栈视图,您不会得到错误:
class ProportionalStackExampleViewController: UIViewController {
let outerStackView: UIStackView = {
let v = UIStackView()
v.translatesAutoresizingMaskIntoConstraints = false
v.axis = .vertical
v.spacing = 8
return v
}()
let outerStackFrame: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.layer.borderWidth = 0.5
v.layer.borderColor = UIColor.blue.cgColor
return v
}()
let infoLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.font = UIFont.systemFont(ofSize: 12.0, weight: .light)
v.numberOfLines = 0
v.textAlignment = .center
v.text = "Red views have intrinsic width of 25\nGreen views have intrinsic width of 75\nAll horizontal stack views are 200-pts wide\nTap any view to see its width"
return v
}()
let sizeLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = "(width)"
return v
}()
let myGreen = UIColor(red: 0, green: 0.75, blue: 0, alpha: 1.0)
override func viewDidLoad() {
super.viewDidLoad()
for _ in 1...6 {
let lbl = UILabel()
lbl.font = UIFont.systemFont(ofSize: 12.0, weight: .light)
lbl.numberOfLines = 0
lbl.textAlignment = .center
outerStackView.addArrangedSubview(lbl)
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.axis = .horizontal
sv.distribution = .fillProportionally
sv.spacing = 0
outerStackView.addArrangedSubview(sv)
}
view.addSubview(infoLabel)
view.addSubview(sizeLabel)
view.addSubview(outerStackFrame)
view.addSubview(outerStackView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
infoLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
infoLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
infoLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
sizeLabel.topAnchor.constraint(equalTo: infoLabel.bottomAnchor, constant: 20.0),
sizeLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
outerStackView.topAnchor.constraint(equalTo: sizeLabel.bottomAnchor, constant: 20.0),
outerStackView.widthAnchor.constraint(equalToConstant: 200.0),
outerStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
outerStackFrame.widthAnchor.constraint(equalTo: outerStackView.widthAnchor),
outerStackFrame.heightAnchor.constraint(equalTo: outerStackView.heightAnchor),
outerStackFrame.centerXAnchor.constraint(equalTo: outerStackView.centerXAnchor),
outerStackFrame.centerYAnchor.constraint(equalTo: outerStackView.centerYAnchor),
])
// StackView 1
if let lbl = outerStackView.arrangedSubviews[0] as? UILabel,
let sv = outerStackView.arrangedSubviews[1] as? UIStackView {
lbl.text = "One view, no layoutMargins"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 2
if let lbl = outerStackView.arrangedSubviews[2] as? UILabel,
let sv = outerStackView.arrangedSubviews[3] as? UIStackView {
lbl.text = "Two views, no layoutMargins"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// comment out this block to see the auto-layout error goes away
// StackView 3
if let lbl = outerStackView.arrangedSubviews[4] as? UILabel,
let sv = outerStackView.arrangedSubviews[5] as? UIStackView {
lbl.text = "One view\nlayoutMargins left: 10 right: 10"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 10, bottom: 0, right: 10)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 4
if let lbl = outerStackView.arrangedSubviews[6] as? UILabel,
let sv = outerStackView.arrangedSubviews[7] as? UIStackView {
lbl.text = "Two views\nlayoutMargins left: 10 right: 10"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 10, bottom: 0, right: 10)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 5
if let lbl = outerStackView.arrangedSubviews[8] as? UILabel,
let sv = outerStackView.arrangedSubviews[9] as? UIStackView {
lbl.text = "layoutMargins left: 100 right: 0"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 100, bottom: 0, right: 0)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
// StackView 6
if let lbl = outerStackView.arrangedSubviews[10] as? UILabel,
let sv = outerStackView.arrangedSubviews[11] as? UIStackView {
lbl.text = "layoutMargins left: 0 right: 100"
var v = ProportionalView()
v.w = 25.0
v.backgroundColor = .red
sv.addArrangedSubview(v)
var tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
v = ProportionalView()
v.w = 75.0
v.backgroundColor = myGreen
sv.addArrangedSubview(v)
sv.isLayoutMarginsRelativeArrangement = true
sv.layoutMargins = .init(top: 0, left: 0, bottom: 0, right: 100)
tg = UITapGestureRecognizer(target: self, action: #selector(showWidth(_:)))
v.addGestureRecognizer(tg)
}
}
@objc func showWidth(_ sender: UITapGestureRecognizer) -> Void {
if let v = sender.view {
sizeLabel.text = "Width: \(v.frame.width)"
sizeLabel.textColor = v.backgroundColor
}
}
}
class ProportionalView: UIView {
var w: CGFloat = 1.0
override var intrinsicContentSize: CGSize {
return CGSize(width: w, height: 40.0)
}
}