I have a horizontal UIStackView
that, by default, looks as follows:
The view with the heart is initially hidden and then shown at runtime. I would like to reduce the spacing between the heart view and the account name view.
The following code does the job, but only, when executed in viewDidLoad
:
stackView.setCustomSpacing(8, after: heartView)
When changing the custom spacing later on, say on a button press, it doesn't have any effect. Now, the issue here is, that the custom spacing is lost, once the subviews inside the stack view change: when un-/hiding views from the stack view, the custom spacing is reset and cannot be modified.
stackView.customSpacing(after: heartView)
(which properly returns 8
) stackView.layoutIfNeeded()
stackView.layoutSubviews()
view.layoutIfNeeded()
view.layoutSubviews()
viewDidLayoutSubviews()
How can I update the custom spacing of my stack view at runtime?
A streamlined interface for laying out a collection of views in either a column or a row.
1) Adjust the external space at the top and bottom outside the stack you are currently editing. Pull the slider right and space above and below your stack will increase, and vice versa if the bar is moved to the left. 2) Adjust the internal space, the top and bottom areas inside the stack you are currently editing.
You need to make sure the UIStackView
's distribution
property is set to .fill
or .fillProportionally
.
I created the following swift playground and it looks like I am able to use setCustomSpacing
at runtime with random values and see the effect of that.
import UIKit
import PlaygroundSupport
public class VC: UIViewController {
let view1 = UIView()
let view2 = UIView()
let view3 = UIView()
var stackView: UIStackView!
public init() {
super.init(nibName: nil, bundle: nil)
}
public required init?(coder aDecoder: NSCoder) {
fatalError()
}
public override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view1.backgroundColor = .red
view2.backgroundColor = .green
view3.backgroundColor = .blue
view2.isHidden = true
stackView = UIStackView(arrangedSubviews: [view1, view2, view3])
stackView.spacing = 10
stackView.axis = .horizontal
stackView.distribution = .fillProportionally
let uiSwitch = UISwitch()
uiSwitch.addTarget(self, action: #selector(onSwitch), for: .valueChanged)
view1.addSubview(uiSwitch)
uiSwitch.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
uiSwitch.centerXAnchor.constraint(equalTo: view1.centerXAnchor),
uiSwitch.centerYAnchor.constraint(equalTo: view1.centerYAnchor)
])
view.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
stackView.heightAnchor.constraint(equalToConstant: 50),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 50),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -50)
])
}
@objc public func onSwitch(sender: Any) {
view2.isHidden = !view2.isHidden
if !view2.isHidden {
stackView.setCustomSpacing(CGFloat(arc4random_uniform(40)), after: view2)
}
}
}
PlaygroundPage.current.liveView = VC()
PlaygroundPage.current.needsIndefiniteExecution = true
Another reason setCustomSpacing
can fail is if you call it before adding the arranged subview after which you want to apply the spacing.
Won't work:
headerStackView.setCustomSpacing(50, after: myLabel)
headerStackView.addArrangedSubview(myLabel)
Will work:
headerStackView.addArrangedSubview(myLabel)
headerStackView.setCustomSpacing(50, after: myLabel)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With