I have a very simple animation block which performs the following animation:
func didTapButton() {
// reset the animation to 0
centerYConstraint.constant = 0
superview!.layoutIfNeeded()
UIView.animate(
withDuration: 1,
animations: {
// animate the view downwards 30 points
self.centerYConstraint.constant = 30
self.superview!.layoutIfNeeded()
})
}
Everything is great when I play the animation by itself. It resets to position 0, then animates 30 points.
The problem is when the user taps the button multiple times quickly (i.e. during the middle of an ongoing animation). Each time the user taps the button, I would expect it to reset to position 0, then animate downwards 30 points. Instead, I get this behavior:
It's clearly traveling well over 30 points. (Closer to 120 points.)
Why is this happening, and how can I "reset" the animation properly so that it only at most travels 30 points?
Things that I have tried that didn't work:
- Using
options: UIViewAnimationOptions.beginFromCurrentState
. It does the same exact behavior. - Instead of executing the animation directly, do it after a few milliseconds using dispatch_after. Same behavior.
- "Canceling" the previous animation by using a
0
second animation that changes the constant to0
, and callssuperview!.layoutIfNeeded
.
Other notes:
- If instead of changing the position, I change the height via a constraint, I get similar odd behavior. E.g. if I set it to go from 30 points to 15 points, when repeatedly pressing the button, the view will clearly grow up to around 120 points.
- Even if I don't use constraints, and instead I animate the
transform
fromCGAffineTransform.identity
toCGAffineTransform(scaleX: 0.5, y: 0.5)
, I get the same behavior where it'll grow to 120 points. - If I try a completely different animatable property say
backgroundColor = UIColor(white: 0, alpha: 0.5)
tobackgroundColor = UIColor(white: 0, alpha: 0)
, then I get correct behavior (i.e. each time I tap the button, the color resets to0.5
gray at most. It never gets to black.