I know that I can add transparent subviews to UIStackView
and set their widths with constraints. The problem is if I want to hide some opaque subviews all the spaces between them remain (and I don't know how to "disable" these spaces properly).
I found setCustomSpacing(_:after:)
:
https://developer.apple.com/documentation/uikit/uistackview/2866023-setcustomspacing
The problem is it sets constant spacing but in my case opaque subviews have constant width and spacing between them varies.
Then I found customSpacing(after:)
and tried to override it:
https://developer.apple.com/documentation/uikit/uistackview/2865827-customspacing
It seems to be the most appropriate solution for me but the problem is the overriden method is never called.
So are there normal ways to add subviews into UIStackView
with proportional spacing and allow to hide these subviews simultaneously with their spacing?
If your spacings varies dynamically, depending on the dimensions of other views, set the spacings in layoutSubviews
, or viewDidLayoutSubviews
if you are in a VC. These are the methods that will be called when some view's dimensions change. There, you can do whatever calculations you like, and compute a value for each view's spacing.
For example, here I have created a stack view with 3 labels. The spacing between the first and second labels is equal to 1/10 of the stack view's width, and the spacing between the second and third labels is equal to 1/20 of the stack view's width (aka one half of the first).
var stack: UIStackView!
override func viewDidLoad() {
func makeLabel(_ text: String) -> UILabel {
let label = UILabel(frame: .zero)
label.text = text
label.backgroundColor = .green
label.sizeToFit()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}
stack = UIStackView(arrangedSubviews: [makeLabel("Foo Bar"), makeLabel("Something"), makeLabel("Else")])
stack.axis = .horizontal
stack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stack)
NSLayoutConstraint.activate([
view.centerYAnchor.constraint(equalTo: stack.centerYAnchor),
stack.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10),
stack.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10)
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
stack.setCustomSpacing(stack.bounds.width / 10, after: stack.arrangedSubviews[0])
stack.setCustomSpacing(stack.bounds.width / 20, after: stack.arrangedSubviews[1])
}