13

Is it possible to animate an arranged subview when its intrinsic content size changes?

For example, imagine I have an arranged subview, which holds a single UILabel pinned to edges. That label has a small amount of text. New text comes in, which is larger than the previous text. The intrinsic content size of label is now larger.

I would like to be able to animate it like so:

 stackView.layoutIfNeeded()
 self.label.text = self.expanded ? textTwo : textOne
 UIView.animateWithDuration(0.3) { () -> Void in
     self.stackView.layoutIfNeeded()
 }

The stackview currently "jumps" from the old content size to the new one, ignoring the animation block.

An alternative of course is to manually find out the height of the arranged subview, and animate that constraint. I'd like to avoid that if possible.

2 Answers2

13

Found something that works:

label.text = expanded ? textOne : textTwo
UIView.animateWithDuration(0.4) { () -> Void in
    self.stackView.setNeedsLayout()
    self.stackView.layoutIfNeeded()
}

Does not work:

label.text = expanded ? textOne : textTwo
UIView.animateWithDuration(0.4) { () -> Void in
    self.stackView.layoutIfNeeded()
}

Strange that changing of the intrinsic content size doesn't make the stackView want to need layout though...

0

Let's think that you have a custom UI element and changing it's intrinsicContentSize

    ...
    var stackView: UIStackView!
    var yourUIElement: UIElement! // (any kind of ui element)
    
    UIView.animate(withDuration: 3, delay: 0) { [weak self] in
       guard let self = self else {return}
            self.yourUIElement.configure() // your configuration
            // in your case this will be label.text = expanded ? textOne : textTwo
            self.stackView.layoutIfNeeded()
            self.stackView.setNeedsLayout()
            self.yourUIElement.invalidateIntrinsicContentSize()
            // in your case this will be self.label.invalidateIntrinsicContentSize()
        }

This worked for me, hope it helps to you

eemrah
  • 1,603
  • 3
  • 19
  • 37