Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift iOS - setContentHuggingPriority is prioritizing the wrong label

I have a cell with 4 labels:

2 separate static labels and 2 separate dynamic labels. The text in the 2 static labels always says Receipt # and the other says Receipt Date.

The way I set it up is the static labels both have leading anchors pinned to the cell's contentView's leadingAnchor. They both have setContentHuggingPriority set to High and setContentCompressionResistancePriority set to Low. Their bottomAnchors are attached to each of their matching dynamic label's lastBaseLineAnchor

The dynamic labels both have their trailing Anchors pinned to the contentView's trailingAnchor.

The receiptNumberLabel's leadingAnchor is pinned to the the receiptDateLabel's leadingAnchor.

The receiptDateLabel's leadingAnchor is pinned 10 points away from the staticReceiptDateLabel. This label is the label that should be flexible but it's not. Since the receiptNumberLabels' leadingAnchor follows this it's misaligned also.

enter image description here

As you can see the staticReceiptDateLabel is longer but it should be shorter and the receiptDateLabel should be longer. I've tried different combinations for the values for setContentHuggingPriority and setContentCompressionResistancePriority but no matter what I keep getting these results, how can I fix this?

contentView.addSubview(receiptNumberLabel) // dynamic
contentView.addSubview(staticReceiptNumberLabel)
contentView.addSubview(receiptDateLabel) // dynamic
contentView.addSubview(staticReceiptDateLabel)

receiptNumberLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
receiptNumberLabel.leadingAnchor.constraint(equalTo: receiptDateLabel.leadingAnchor, constant: 0).isActive = true
receiptNumberLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true
receiptNumberLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
receiptNumberLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)

staticReceiptNumberLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10).isActive = true
staticReceiptNumberLabel.lastBaselineAnchor.constraint(equalTo: receiptNumberLabel.lastBaselineAnchor).isActive = true
staticReceiptNumberLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
staticReceiptNumberLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

receiptDateLabel.topAnchor.constraint(equalTo: receiptNumberLabel.bottomAnchor, constant: 10).isActive = true
receiptDateLabel.leadingAnchor.constraint(equalTo: staticReceiptDateLabel.trailingAnchor, constant: 10).isActive = true
receiptDateLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true
receiptDateLabel.setContentHuggingPriority(UILayoutPriority.defaultLow, for: .horizontal)
receiptDateLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)

staticReceiptDateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10).isActive = true
staticReceiptDateLabel.lastBaselineAnchor.constraint(equalTo: receiptDateLabel.lastBaselineAnchor).isActive = true
staticReceiptDateLabel.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .horizontal)
staticReceiptDateLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)

UPDATE

In the comments @bsod suggested not to use the hugging/compression at all. I initially didn't use them and the same problem occurred, I switched to them as a last resort. Here is the code without the hugging/compression.

receiptNumberLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
receiptNumberLabel.leadingAnchor.constraint(equalTo: receiptDateLabel.leadingAnchor, constant: 0).isActive = true
receiptNumberLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true

staticReceiptNumberLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10).isActive = true
staticReceiptNumberLabel.lastBaselineAnchor.constraint(equalTo: receiptNumberLabel.lastBaselineAnchor).isActive = true

receiptDateLabel.topAnchor.constraint(equalTo: receiptNumberLabel.bottomAnchor, constant: 10).isActive = true
receiptDateLabel.leadingAnchor.constraint(equalTo: staticReceiptDateLabel.trailingAnchor, constant: 10).isActive = true
receiptDateLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true

staticReceiptDateLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10).isActive = true
staticReceiptDateLabel.lastBaselineAnchor.constraint(equalTo: receiptDateLabel.lastBaselineAnchor).isActive = true
like image 626
Lance Samaria Avatar asked Oct 25 '25 14:10

Lance Samaria


1 Answers

Forget the hugging/compression API and use this as a starting point. Start with the upper-left label and work your way down left-to-right, top-to-bottom. Notice that the static date label's top anchor is pinned to the bottom of the receipt number's value label in case it has more than one line.

staticReceiptNumberLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10).isActive = true
staticReceiptNumberLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true

receiptNumberLabel.topAnchor.constraint(equalTo: staticReceiptNumberLabel.topAnchor).isActive = true
receiptNumberLabel.leadingAnchor.constraint(equalTo: staticReceiptNumberLabel.trailing, constant: 10).isActive = true
receiptNumberLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true

staticReceiptDateLabel.leadingAnchor.constraint(equalTo: staticReceiptNumberLabel.leadingAnchor).isActive = true
staticReceiptDateLabel.topAnchor.constraint(equalTo: receiptNumberLabel.bottomAnchor).isActive = true

receiptDateLabel.topAnchor.constraint(equalTo: staticReceiptDateLabel.topAnchor).isActive = true
receiptDateLabel.leadingAnchor.constraint(equalTo: staticReceiptDateLabel.trailingAnchor, constant: 10).isActive = true
receiptDateLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true
receiptDateLabel.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10).isActive = true

You also likely need to explicitly set the title labels' numberOfLines to 1 otherwise UIKit may truncate the value label even if its numberOfLines is 0.

If, for whatever reason, you don't even want the static labels to expand in size, perhaps because you give them a background color, then you can introduce the hugging/compression API. If so, the static labels would be:

theStaticLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
theStaticLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)

and the dynamic labels would be:

theDynamicLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
theDynamicLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
like image 158
liquid LFG UKRAINE Avatar answered Oct 28 '25 04:10

liquid LFG UKRAINE



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!