1

I have a UIStackView, and as arranged subviews, I have two UIViews, and a UILabel. The UIViews are stacked one after another, while the UILabel is aligned to the leading edge of the subview.

Code:

let stack = UIStackView()
stack.axis = .horizontal
stack.distribution = .fillProportionally
stack.alignment = .center
stack.spacing = 7
view.addSubview(stack)
stack.translatesAutoresizingMaskIntoConstraints = false
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

let icon = UIView()
icon.backgroundColor = UIColor.red
stack.addArrangedSubview(icon)
icon.translatesAutoresizingMaskIntoConstraints = false
icon.heightAnchor.constraint(equalToConstant: 42).isActive = true
icon.widthAnchor.constraint(equalToConstant: 42).isActive = true

let icon2 = UIView()
icon2.backgroundColor = UIColor.red
stack.addArrangedSubview(icon2)
icon2.translatesAutoresizingMaskIntoConstraints = false
icon2.heightAnchor.constraint(equalToConstant: 42).isActive = true
icon2.widthAnchor.constraint(equalToConstant: 42).isActive = true

let label = UILabel()
label.lineBreakMode = .byWordWrapping
label.numberOfLines = 0
label.sizeToFit()
label.translatesAutoresizingMaskIntoConstraints = false
label.backgroundColor = .yellow
label.text = "Hello World! Again"
label.textColor = .black
stack.addArrangedSubview(label)

Output: enter image description here

rawbee
  • 2,946
  • 3
  • 18
  • 22
  • A multiline label *does not have an intrinsic width* (well, it does, but not in the way you're trying to use it). You have to give it a width in some way, either by constraint or by constraining the width of its container - in this case, the width of your stack view. – DonMag Mar 30 '18 at 20:04

2 Answers2

2

For clarity...

First, don't use .fillProportionally. Whatever you think that will do, it's wrong. You have explicitly set your two "icons" to be 42-pts wide each. If the stack view is using .fillProportionally, it will try to change the widths of those views, and you will get auto-layout conflicts.

Second, a UILabel with .numberOfLines = 0 must have a width. Otherwise, there is no way to know where to break the text... with a lot of text, it will extend way off the sides of the view.

Third, the line label.sizeToFit() isn't going to accomplish anything here. Just delete it.

If you add this line:

stack.widthAnchor.constraint(equalToConstant: 200.0).isActive = true

then the stack view will expand to 200-pts wide...

Auto-layout will give the first arranged view a width of 42 (because that's what you declared it to be), and the same for the second view. Since you've set the spacing to 7, it will then calculate

42 + 7 + 42 + 7

which equals 98. It subtracts that from the stack view's width:

200 - 98 = 102

and that is the width it will give your label.

Result:

enter image description here

If you don't want to explicitly set the width to 200, you can set it to a percentage of the superview's width, or give it leading and trailing constraints.

DonMag
  • 69,424
  • 5
  • 50
  • 86
1

Try to change distribution to fill

stack.distribution = .fill

With multiline set

enter image description here

After commenting it

enter image description here

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • So that does put it in the stack (yay), but it doesn't respect the intrinsic size of the uilabel, i.e. it squashes it so that it's the same width as the other two UIViews, and causes the text to break after just about every word. – rawbee Mar 30 '18 at 20:02
  • to make it stretch comment .lines , or give it a width – Shehata Gamal Mar 30 '18 at 20:06