0

I have a UIScrollView that fills all the window and that contains a vertical UIStackView where I want to add UILabels that fill all available width.

The UIStackView is pinned to all the edges of UIScrollView, and I expect it to fill all the UIScrollView. But it seems that it completely ignores all the constriants and it only sizes to fit it's childs. Why that behaviour?

To illustrate that if I add labels that way:

    scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[stackView]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["stackView": stackView]))
    scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[stackView]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["stackView": stackView]))

    for _ in 1 ... 20 {
        let textLabel = UILabel()
        textLabel.backgroundColor = UIColor.yellow
        textLabel.text  = "Hi World xxxx"
        stackView.addArrangedSubview(textLabel)
        textLabel.widthAnchor.constraint(equalTo: stackView.widthAnchor).isActive = true //Doesn't work as expected

    }

what I get is this: (the cyan background is the UIScrollView and you can see that labels doesn't take all width due to that UIStackView contraints doesn't apply)

Result with stackview contraints

And only if I change the label contraint to use scrollView it works as desired:

textLabel.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

Then the result is as expected: enter image description here

Why that behaviour? Someone can explain why the constraints on UIStackView doesn't work as I expect?

Complete source code avaiable at that gist

shallowThought
  • 19,212
  • 9
  • 65
  • 112
lujop
  • 13,504
  • 9
  • 62
  • 95

1 Answers1

1

Everything is correct. Its just that you have not specified the width of the content view(the stack view). Add this line and thing will work perfectly.

scrollView.widthAnchor.constraint(equalTo: stackView.widthAnchor, multiplier: 1).isActive = true;

Note: Pinning scroll view's leading trailing with content view does, not provide the width to the content view. A separate width constraint is required, other wise the content view will have its width equal to its intrinsic width. Links: https://stackoverflow.com/a/18341997/1790683

Community
  • 1
  • 1
BangOperator
  • 4,377
  • 2
  • 24
  • 38
  • Thanks @BangOperator. Do you have more information on why the width constraint is needed? Normally pinning to borders it's enough to determine width, it isn't? – lujop Nov 25 '16 at 08:47
  • Yes scrollviews a a bit different. You can google uiscrollview with autolayout. I will paste relevant links soon – BangOperator Nov 25 '16 at 09:01