I have a UIStackView
with 5 subviews. I want to be able to animate the width of these subviews by updating their intrinsicContentSize
or updating their constraints. How can I make the stackView redraw after updating the subview's layout?
UIView.animateWithDuration(0.3, animations: {
viewToResize.compressed = true //changes intrinsicContentSize
viewToResize.invalidateIntrinsicContentSize()
self.stackView.layoutIfNeeded() //makes no difference
anotherSubview.hidden = true //adding this makes everything work
})
I have tried various ways of trying to get the stackView to update, but nothing happens. The only way I can make it work is if I show/hide another subview inside the animation block, then the new layout is animated correctly, but I don't want to do this.
I have seen this question Animating UIStackView arrangedSubview content size change but the suggested answer does not work (nothing animates).
The UIStackView is a nonrendering subclass of UIView; that is, it does not provide any user interface of its own. Instead, it just manages the position and size of its arranged views. As a result, some properties (like backgroundColor) have no effect on the stack view.
A layout where the stack view resizes its arranged views so that they fill the available space along the stack view’s axis. When the arranged views do not fit within the stack view, it shrinks the views according to their compression resistance priority.
In general, if you are experiencing issues with auto-layout and UIStackView, set the vertical and horizontal constraints to lower priority. It depends what axis of an UIStackView you use. If horizontal, you have to update the leading, and trailing constraints priority of your arranged subviews.
The first key property of UIStackView is its distribution. This property determines how the stack view lays out its views in the direction of its axis (i.e. for a vertical stack view, distribution determines the height/vertical position of its arranged subviews). There are 5 options:
You don't need viewToResize.invalidateIntrinsicContentSize()
, update constraint of your subviews instead. In the code below, we have two subviews in the stackView
, and we create a widthConstraint
outlet from storyboard. Then we can animate the width of the subview by updating the constant of widthConstraint
in animation block. Note: If a view is contained in a stack view and you try to modify the view frame, it should not change
class ViewController: UIViewController {
@IBOutlet var widthConstraint: NSLayoutConstraint!
@IBOutlet var stackView: UIStackView!
var compressed: Bool = true
@IBOutlet var start: UIButton!
@IBAction func onStart(sender: UIButton) {
UIView.animateWithDuration(3.0,
delay: 0.0,
usingSpringWithDamping: 0.3,
initialSpringVelocity: 10.0,
options: .CurveLinear,
animations: { () -> Void in
//self.stackView.invalidateIntrinsicContentSize()
self.widthConstraint.constant = (self.compressed == false) ? 100.0 : 200.0
self.compressed = !self.compressed
self.view.layoutIfNeeded()
}, completion: nil)
}
For more details, you can have a look at this great blog UIStackView, Auto Layout and Core Animation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With