Emre Önder
Emre Önder

Reputation: 2537

Horizontal UIStackView with two label (one multiline label, one one-line)

I have a horizontal UIStackView which has two UILabel in it. First UILabel is multiline (two line) and other one is one line only. They both have default content compression and resistance priorities. My problem is that even there is a gap between labels, "best" word in first text goes second line. I noticed that first label doesn't goes beyond half of total width.

What I want is that second label should always show itself and first label should size It self for remaining space. If It can't fit to one line It should be two line. However, If second label is too short and first label is a long one but both of them can fit, first label should go beyond half of the width.

P.S I need to use UIStackView in this scenario because there are other cases. I know putting two label inside UIView may solve the problem.

UIStackView:
   - Distribution: Horizontal
   - Alignment: Center
   - Spacing: 0
   UILabel:
     - Number of line: 2
     - Line break: Word wrap
   UILabel:
     - Number of line: 1

Screenshot

View hierarchy:

enter image description here

Desired Result:

enter image description here

OR

enter image description here

EDIT: I calculate the width of second label and give width constraint. I think It solved my problem, I'll test a bit.

        //Give specific width to second label to make first one calculate right number of lines.
    if let font = UIFont(name: "Metropolis-ExtraBold", size: 15) {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = (secondLabelText as NSString).size(withAttributes: fontAttributes)
        secondLabel.widthAnchor.constraint(equalToConstant: size.width).isActive = true
    }

Upvotes: 20

Views: 11006

Answers (3)

DonMag
DonMag

Reputation: 77423

To try and simplify...

Forget calculating any widths... what matters is the horizontal Content Hugging and Content Compression Resistance

Leave the left (blue) label at the defaults:

Content Hugging Priority
    Horizontal: 251

Content Compression Resistance Priority:
    Horizontal: 750

But set the right (orange) label to:

Content Hugging Priority
    Horizontal: 1000

Content Compression Resistance Priority:
    Horizontal: 1000

Results:

enter image description here

The only other issue would be if the text in the right-side label exceeds the full width of the view -- but you haven't indicated that you might need that much text.

Upvotes: 35

Maci
Maci

Reputation: 123

First embed your multiline label inside a view and constraint the label to this view (top, leading, trailing, bottom). After that add your view with your multiline label and single line label to your stackView.

Then you can use .fillProportionally for the distribution of your UIStackView and the spacing value to specify the space between your two labels.

Make also sure to use Required (1000) for your horizontal content compression resistance priority on your right number label.

View-hierarchy:

enter image description here

Result:

enter image description here

enter image description here

With spacing between your labels:

enter image description here

Upvotes: 0

Mojtaba Hosseini
Mojtaba Hosseini

Reputation: 119128

You should set different horizontal content compression resistants for each of them:

Multiple values

For this case, the blue one(multiline) should have something less than the orange one(Singleline).

Assistive note: Multiline: 250, Singleline: 750

Orange Settings: Orange Settings

Blue Settings: OrangeSettings

Note that I have set the line limit of the orange one to 0. You can set it to anything you like. But if you like to make it selfsize to anyhight taller view should have higher vertical compression resistant than 250.

Upvotes: 2

Related Questions