Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I enclose "addArrangedSubview" to the animation block or not?

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?

like image 208
Blaszard Avatar asked Jan 07 '23 14:01

Blaszard


1 Answers

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.

like image 155
Rob Norback Avatar answered Jan 21 '23 03:01

Rob Norback