There is a problem if you have a UIStackView(testStack)
and a placeholder UIView(testView)
inside another UIStackView(mainStack)
. It is meant that if there is no content in the testStack
it will collapse, and the testView
will take all the space. There is even a content hugging priority
set to maximum for the testStack
so it should collapse its height to 0 when there are no subviews. But it does not. How to make it collapse when there is no content?
PS If there are items in the testStack
, everything works as expected: testView
takes all available space, testStack
takes only the space to fit its subviews.
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")
}
}
When auto-layout arranges subviews in a UIStackView
, it looks at:
.distribution
propertySince you have not specified a .distribution
property, mainStack
is using the default of .fill
.
A UIStackView
has NO Intrinsic Content Size, so auto-layout says "testStack has a height of Zero"
A UIView
has NO Intrinsic Content Size, so auto-layout says "testView has a height of Zero"
Since the distribution is fill, auto-layout effectively says: "the heights of the arranged subviews are ambiguous, so let's give the last subview a height of Zero, and fill mainStack with the first subview.
Setting .setContentHuggingPriority
will have no effect, because there is no intrinsic height to "hug."
If you set mainStack's .distribution = .fillEqually
, you will get (as expected) testStack
filling the top half, and testView
filling the bottom half.
If you set mainStack's .distribution = .fillProportionally
, you will get the same result... testStack
filling the top half, and testView
filling the bottom half, because .fillProportionally
uses the arranged subviews' Intrinsic Content Sizes... in this case, they are both Zero, so "proportional" will be equal.
If you set mainStack's .distribution = .equalSpacing
or .distribution = .equalCentering
, you won't see either testStack
or testView
... auto-layout will give each of them a height of Zero, and fill the rest of mainStack
with (empty) "spacing."
If your goal is to have testStack
"disappear" if it is empty, you can either: