I'm not learning the use of UIStackView
and read a good tutorial on the web. In the tutorial, the author writes the following code to make an animation:
@IBAction func addStar(sender: AnyObject) {
let starImgVw:UIImageView = UIImageView(image: UIImage(named: "star"))
starImgVw.contentMode = .ScaleAspectFit
self.horizontalStackView.addArrangedSubview(starImgVw)
UIView.animateWithDuration(0.25, animations: {
self.horizontalStackView.layoutIfNeeded()
})
}
However, when I cloned the repository and changed the code slightly, I still saw the same animation properly.
@IBAction func addStar(sender: AnyObject) {
let starImgVw:UIImageView = UIImageView(image: UIImage(named: "star"))
starImgVw.contentMode = .ScaleAspectFit
UIView.animateWithDuration(0.25, animations: {
self.horizontalStackView.addArrangedSubview(starImgVw)
self.horizontalStackView.layoutIfNeeded()
})
}
I moved self.horizontalStackView.addArrangedSubview(starImgVw)
to the inner part of the animation block.
I also tried the same thing on removeStar
function; this time moved both self.horizontalStackView.removeArrangedSubview(aStar)
and aStar.removeFromSuperview()
, but I also confirmed the animation work properly.
So my question is the following:
Which is the better way?
Why do these two code work in the same way?
When I removed layoutIfNeeded()
, then the animation didn't work. This is because if I don't force the views to be updated immediately, then the next view update cycle occurs after the animation block and thus the animation is no longer valid, right?
In an animation block, you just want to include the change that you want to see animated. You shouldn't include several changes at the same time because then the functionality becomes a bit unpredictable. You won't be sure which change will take precedence over the others.
So to answer your question, the first example you have with
UIView.animateWithDuration(0.25, animations: {
self.horizontalStackView.layoutIfNeeded()
})
is the better way to write this piece of code.
Only specific properties of UIView are animatable. From Apple's docs:
The following properties of the UIView class are animatable:
@property frame
@property bounds
@property center
@property transform
@property alpha
@property backgroundColor
@property contentStretch
Essentially, by calling layoutIfNeeded
, you are allowing animateWithDuration
to animate the adding of constraints to the star view before it's laid out by the processor. That's why you see it move to the right.
Removing layoutIfNeeded()
would just leave your adding a subview function. Adding a subview is not animatable with the animateWithDuration function. That's why it didn't work. You can make it look animated by setting alpha to 0.0 when you first create it and then in animateWithDuration
set alpha to 1.0.
starImgVw.alpha = 0.0
horizontalStackView.addArrangedSubview(starImgVw)
UIView.animateWithDuration(0.25) { () -> Void in
starImgVw.alpha = 1.0
}
I hope that answers your questions fully.
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