I'm creating a vertical UIStackView where arranged subviews will start from top. Subviews quantity will be 5 at most. Here are my expectation, reality and code. Any Idea?
Expectation
Current situation
Code
var homeVStack: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.alignment = .top
stackView.distribution = .equalSpacing
stackView.spacing = 20
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
private func loadData() {
if let homeFormList = data?.homeTeamForm {
for homeForm in homeFormList {
let teamFormView = SimpleScoreView()
teamFormView.teamForm = homeForm
teamFormView.heightAnchor.constraint(equalToConstant: 50).isActive = true
teamFormView.backgroundColor = .yellow
homeVStack.addArrangedSubview(teamFormView)
}
}
}
You are explicitly setting the Height of the subviews:
teamFormView.heightAnchor.constraint(equalToConstant: 50).isActive = true
So, do NOT give your stackView a Bottom anchor or Height constraint.
Here's a quick example...
SimpleScoreView -- view with a centered label:
class SimpleScoreView: UIView {
let scoreLabel = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
self.backgroundColor = .yellow
scoreLabel.textAlignment = .center
scoreLabel.translatesAutoresizingMaskIntoConstraints = false
scoreLabel.backgroundColor = .green
addSubview(scoreLabel)
NSLayoutConstraint.activate([
scoreLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
scoreLabel.centerYAnchor.constraint(equalTo: centerYAnchor),
])
}
}
Basic View Controller -- each tap will add another "Score View":
class ViewController: UIViewController {
var homeVStack: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
// these two are not needed
//stackView.alignment = .top
//stackView.distribution = .equalSpacing
stackView.spacing = 20
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(homeVStack)
// respect safe area
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// constrain stack view Top / Leading / Trailing
homeVStack.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
homeVStack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
homeVStack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
])
loadData()
}
// for this example, loadData() will add one new
// SimpleScoreView each time it's called
private func loadData() {
let v = SimpleScoreView()
v.heightAnchor.constraint(equalToConstant: 50).isActive = true
v.scoreLabel.text = "\(homeVStack.arrangedSubviews.count + 1)"
homeVStack.addArrangedSubview(v)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
loadData()
}
}
Results: