Bubu
Bubu

Reputation: 669

Swift - auto layout UILabel height based on its contents

I am having trouble setting up auto layout for UILabel and would like to get help on this.

enter image description here

In the picture, I have created yellow and green UILabels.

What I want to achieve is dynamically adjust the yellow UILabel height based on its content's number of lines, and anchor top of green box to anchor bottom of yellow box.

Currently, I have code as follow:

// Yellow UILabel
addSubview(captionLabel)
captionLabel.anchor(top: actionButtonsStackView.bottomAnchor, left: leadingAnchor, bottom: nil, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)
captionLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true

// Green UILabel
addSubview(dateLabel)
dateLabel.anchor(top: captionLabel.bottomAnchor, left: leadingAnchor, bottom: bottomAnchor, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)

Note: the anchor function sets top, leading, bottom, and trailing constraints with respective paddings.

As you can see, the yellow UILabel takes up more space than it actually needs.

If I leave top constraint from green UILabel, the yellow box actually starts to work as I expect:

enter image description here

And the code for this looks like:

// Yellow UILabel
addSubview(captionLabel)
captionLabel.anchor(top: actionButtonsStackView.bottomAnchor, left: leadingAnchor, bottom: nil, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)
captionLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true

// Green UILabel
addSubview(dateLabel)
dateLabel.anchor(top: nil, left: leadingAnchor, bottom: bottomAnchor, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)

What am I doing wrong here?


Actually, removing bottomAnchor from green box make it work: enter image description here

And the code for this looks like:

// Yellow UILabel
addSubview(captionLabel)
captionLabel.anchor(top: actionButtonsStackView.bottomAnchor, left: leadingAnchor, bottom: nil, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)
captionLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true

// Green UILabel
addSubview(dateLabel)
dateLabel.anchor(top: captionLabel.bottomAnchor, left: leadingAnchor, bottom: nil, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)

But why is it working? I thought by setting greaterThenOrEqual constant, the yellow UILabel auto size itself to just enough size to contain its contents, and the green UILabel adjust its size accordingly to bottomAnchor's yellow UILabel.

Upvotes: 0

Views: 708

Answers (1)

Dai Tran
Dai Tran

Reputation: 11

That because you're adding two labels which have same priority of vertical content hugging (low by default). If you want the the green label get higher, you can set the Content Hugging Priority value of the red one to high or required. Here the code:

// Yellow UILabel
addSubview(captionLabel)
captionLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
captionLabel.anchor(top: actionButtonsStackView.bottomAnchor, left: leadingAnchor, bottom: nil, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)

// Green UILabel
addSubview(dateLabel)
dateLabel.anchor(top: captionLabel.bottomAnchor, left: leadingAnchor, bottom: bottomAnchor, right: trailingAnchor, paddingTop: 0, paddingLeft: 8, paddingBottom: 0, paddingRight: 8, width: 0, height: 0)

For more details you can this article: https://medium.com/@abhimuralidharan/ios-content-hugging-and-content-compression-resistance-priorities-476fb5828ef

Upvotes: 1

Related Questions