I have a simple pulse animation which runs perfectly
UIView.animate(withDuration: 1, animations: {
myAnimatableView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}) { _ in
UIView.animate(withDuration: 1, animations: {
myAnimatableView.transform = .identity
})
}
I want to make the same animation, but now with UIViewPropertyAnimator
. Is it possible to replicate this pulse effect elegantly with the new API?
I'm doing it this way
let animator = UIViewPropertyAnimator(duration: 1, curve: .linear) {
animatableView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}
animator.addCompletion { _ in
animator.isReversed = true
animator.startAnimation()
}
animator.startAnimation()
but my animatableView
is just stuck scaled to 1.2.
It seems that the property animator removes animations after completion (which would explain that starting it again would have no effect) - see SO question. Based on that, You might try hacking it through pausesOnCompletion
, but I would expect that that would not be as easy as you might think. Simply because the documentation says:
When the value of this property is true, the animator remains in the active state when the animation finishes, and it does not execute its completion handler.
That means that completion handler won't get called, if the pauseOnCompletion
is set to true. According to the same documentation, you can determine when the animator ended (and thus when you should restart the animation) by observing isRunning
property of the animator. However, when I tried to implement that, I found out that KVO on isRunning
does not get called during the lifecycle of the animator. Thus my recommendation in the end is to simply use two animators, because it seems much easier to implement:
let animator = UIViewPropertyAnimator(duration: 1, curve: .linear) {
animatableView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}
animator.addCompletion { _ in
let secondAnimator = UIViewPropertyAnimator(duration: 1, curve: .linear) {
animatableView.transform = CGAffineTransform.identity
}
secondAnimator.startAnimation()
}
animator.startAnimation()
I think your code is more appropiated translated like this
Try with this code
let animator = UIViewPropertyAnimator(duration: 1, curve: .linear) {
self.animatableView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
}
animator.addAnimations({
self.animatableView.transform = CGAffineTransform.identity
}, delayFactor: 0.5)
animator.startAnimation()
Or you can try with UILayer
animations
Try using UILayer animations
let layerAnimation = CABasicAnimation(keyPath: "transform.scale")
layerAnimation.fromValue = 1
layerAnimation.toValue = 1.2
layerAnimation.isAdditive = false
layerAnimation.duration = CFTimeInterval(1)
layerAnimation.fillMode = kCAFillModeForwards
layerAnimation.isRemovedOnCompletion = true
layerAnimation.repeatCount = .infinity
layerAnimation.autoreverses = true
self.animatableView.layer.add(layerAnimation, forKey: "growingAnimation")
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