Reputation: 110
I'm trying to programmatically create a 3x33 grid of UIButton
s using nested UIStackView
s inside a UIScrollView
. The outer UIStackView
has a vertical axis, while the inner UIStackView
s have horizontal axes and distribution = .fillEqually
.
If I don't have the enclosing UIScrollView
, the buttons properly fill the width of the screen. With the scroll view, however, the buttons fill only half the width of the screen.
Here is a code example. In IB, ViewController
's view
property has been set to a UIScrollView
instance.
class ViewController: UIViewController {
var stackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
title = "No Filling :("
stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.spacing = 5
view.addSubview(stackView)
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[stackView]-|", options: .alignAllCenterX, metrics: nil, views: ["stackView": stackView!]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[stackView]|", options: .alignAllCenterY, metrics: nil, views: ["stackView": stackView!]))
for _ in 1...33 {
let hView = UIStackView()
hView.translatesAutoresizingMaskIntoConstraints = false
hView.axis = .horizontal
hView.distribution = .fillEqually
hView.spacing = 5
stackView.addArrangedSubview(hView)
stackView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[hView]|", options: .alignAllCenterX, metrics: nil, views: ["hView": hView]))
for i in 1...3 {
let button = UIButton(type: .system)
button.setTitle("Button \(i)", for: .normal)
hView.addArrangedSubview(button)
button.layer.borderWidth = 1
button.layer.cornerRadius = 7
}
}
}
}
Upvotes: 0
Views: 269
Reputation: 154563
You want your scrollView's content width to be the width of the scrollView itself so that it fills the screen and scrolls vertically.
In order to do that, you need to establish the width of the scrollView's content. Right now, it is getting its width from the intrinsic size of the three buttons.
You need to add a constraint that explicitly makes the scrollView's content (the stackView + left and right offsets) equal to the width of the scrollView:
view.addConstraints(NSLayoutConstraint.constraints(
withVisualFormat: "H:|-20-[stackView]-20-|", options: .alignAllCenterX,
metrics: nil, views: ["stackView": stackView!]))
view.addConstraints(NSLayoutConstraint.constraints(
withVisualFormat: "V:|[stackView]|", options: .alignAllCenterY,
metrics: nil, views: ["stackView": stackView!]))
stackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
Note: The adjustment constant
-40
is the sum of the left and right offsets (20
each). In order for the scrollView to not scroll horizontally: stackView.width + 20 + 20 == scrollView.width
, or equivalently, stackView.width == scrollView.width - 40
which is what the constraint specifies.
Upvotes: 1