Force a view to take as much space as possible inside UIStackView
Asked Answered
K

2

14

I'm creating part of my application's UI with Swift and the problem I'm facing is I have a UIStackView with 3 sub views: 2 UILabels and an UIImageView. Here is my first code

let switchview = UISwitch()
let nodelableview = UILabel()
nodelableview.textAlignment = NSTextAlignment.right
nodelableview.numberOfLines = 0
nodelableview.text = nodes[i].type + " " + nodes[i].node_name
let statLabel = UILabel()
statLabel.textAlignment = NSTextAlignment.left
statLabel.text = nodes[i].stat
let stack = UIStackView()
stack.axis = .horizontal
stack.spacing = 16
stack.addArrangedSubview(statLabel)
stack.addArrangedSubview(nodelableview)
stack.addArrangedSubview(switchview)
cell.nodesView.addArrangedSubview(stack)

the problem with this code is that when the nodelabelview has long text the UIStackView not extending to make space for 2 or more lines. So I set the alignment to .center and here is the result enter image description here

There is empty space left but the first UILabel is using it for nothing. How can I force the second UILabel to use available spaces?

Kutuzov answered 24/5, 2018 at 14:14 Comment(5)
You can try to set the distribution to "Fill Proportionally" and content compression resistance (horizontal) of the left label and the switch to 1000.Hyson
What does this cell.nodesView.addArrangedSubview(stack) line actually do? Are you inserting this horizontal stack view inside another stack view of your cell namely nodesView? Why is that necessary?Operculum
I have a cell inside my tableview to filter other cells inside tableview and I'm adding filter options to it @OperculumKutuzov
thanks that solved my problem. please post it as an answer @HysonKutuzov
@Kutuzov Done. Glad that helped you :)Hyson
H
30

A setup that would give priority to your second label (the one with unlimited number of lines), would be a stackview set to "Fill Proportionally" distribution (which means that views are sized based on their intrinsic size & hugging/resistance priorities)

enter image description here

combined with a horizontal "Content Compression Resistance Priority" of 1000 ('required') for the left label & the switch (which means 'do not compress')

enter image description here

which is resolved to this:

enter image description here

Hyson answered 24/5, 2018 at 22:18 Comment(3)
Keep in mind that priorities of 1000 are best avoided in content compression where the actual content size is liable to change, since they can very easily break the rest of the layout. This can especially be the case in stack views where the item in question may be set hidden, since stack views use constraints to collapse hidden elements.Colby
@Colby True... but none of these cases was mentioned in the question. Having said that, your point is valid (I cannot count the times I've seen logged warnings due to hidden managed views with 'required' priority). Thanks for your comment :)Hyson
Yeah, or messed up a stack view because two of the rows have the same hugging / compression values :DColby
C
4

You may need to set the horizontal contentHuggingPriority and contentCompressionResistance for each label / switch to something different from the others, ensuring that the one you wish to expand to fill remaining available space has the lowest hugging value.

Colby answered 24/5, 2018 at 14:20 Comment(2)
When you add a view to a container view, it is the container view's responsibility to control translatesAutoresizingMaskIntoConstraints.Epa
That's nice to know, although I think the rest of the answer remains relevant. I've edited my answer to reflect this. I won't echo Alladinian's response.Colby

© 2022 - 2024 — McMap. All rights reserved.