Reputation: 2601
I have a label containing quite a lot of text. There's a toggle for collapsing and expanding the height of the label (here it's named "lire la suite") so it truncates the end of the text.
I have meticulously set the vertical content hugging priority and compression resistance so the intrinsic size has higher priority over the compression resistance.
The height constraint (the optional constraint directly at the right of the label) is set with a constant of 71
, just the height for 4 lines. It never changes.
Then this same constraint has a priority switching between 747
and 749
so the following happens:
height constraint priority = 749
:
compression resistance < constraint priority < hugging priority
Compression resistance collapses under the constraint priority, its height is
71
or less if its intrinsic size (hugging priority) is smaller.
height constraint priority = 747
:
constraint priority < compression resistance < hugging priority
The greater compression resistance forces the height to follow its intrinsic size.
This works perfectly. My issue is that I can't figure out how to animate this constraint, since every solution animates the constant
property and not the priority
.
I would like to know if there's a solution or a workaround.
Upvotes: 3
Views: 1111
Reputation: 19757
By experimenting with it, it seems that you cannot animate constraints using priorities, and you are stuck either with activating/deactivating constraints, or changing their constants.
I've had a similar task a couple of days ago. An easy but a bit naive approach is to drop the constraint and use only intrinsic content size - you can set the label.numberOfLines = 4
when it should be collapsed (thus the size won't expand over 4 lines), and label.numberOfLines = 0
when expanded. This is very easy and clean, however, I am not sure how that goes with animation.
A second approach is to use only the constraint and animate the constant. You have a height for 4 lines already, all you need is the height of the expanded label. You can use following extension on UILabel
to calculate the height:
extension UILabel {
func heightNeeded() -> CGFloat {
self.layoutIfNeeded()
let myText = self.text! as NSString
let boundingRectangle = CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude)
let labelSize = myText.boundingRect(with: boundingRectangle,
options: .usesLineFragmentOrigin,
attributes: [NSAttributedStringKey.font: self.font],
context: nil)
return labelSize.height
}
}
Then all you need to animate is the:
labelHeightConstraint.constant = label.heightNeeded()
Don't forget on how to animate that constant using autolayout, see for example my following answer to another SO question.
Upvotes: 1