Animate a layout constraint by changing its priority value

十年热恋 提交于 2019-12-11 02:21:53

问题


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.


回答1:


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.



来源:https://stackoverflow.com/questions/48061675/animate-a-layout-constraint-by-changing-its-priority-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!