zcash-android-wallet-zcon1/zcash-android-wallet-app/app/src/main/java/cash/z/android/wallet/ui/util/LottieLooper.kt

89 lines
2.9 KiB
Kotlin

package cash.z.android.wallet.ui.util
import android.animation.Animator
import cash.z.android.wallet.extention.Toaster
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieDrawable
/**
* Utility to help with looping a lottie animation over a particular range. It will start the animation and play it up
* to the end of the range and then set it to loop over the range and, once stopped, it will proceed from the current
* frame to the end of the animation. Visually: BEGIN...LOOP...LOOP...LOOP...END
*/
class LottieLooper(private val lottie: LottieAnimationView, private val loopRange: IntRange, private val lastFrame: Int = Int.MAX_VALUE) :
Animator.AnimatorListener {
var isPlaying = false
fun start() {
if (isPlaying) return
with(lottie) {
setMinAndMaxFrame(1, loopRange.last)
progress = 0f
repeatCount = 0
addAnimatorListener(this@LottieLooper)
playAnimation()
}
isPlaying = true
}
fun stop() {
with(lottie) {
setMinAndMaxFrame(lottie.frame, lastFrame)
repeatCount = 0
// we don't want to just cancel the animation. We want it to finish it's final frames but the moment it is
// done, we need it to freeze on that final frame and then die
addAnimatorListener(LottieAssassin())
}
isPlaying = false
}
override fun onAnimationRepeat(animation: Animator?) {
}
override fun onAnimationEnd(animation: Animator?) {
with(lottie) {
removeAllAnimatorListeners()
setMinAndMaxFrame(loopRange.first, loopRange.last)
repeatCount = LottieDrawable.INFINITE
playAnimation()
}
}
override fun onAnimationCancel(animation: Animator?) {
}
override fun onAnimationStart(animation: Animator?) {
}
/** I have one job: kill lottie */
inner class LottieAssassin : Animator.AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {
finishingMove()
}
override fun onAnimationEnd(animation: Animator?) {
finishingMove()
}
override fun onAnimationCancel(animation: Animator?) {
finishingMove()
}
override fun onAnimationStart(animation: Animator?) {
finishingMove()
}
/** Agressively force it to freeze on the lastframe */
private fun finishingMove() {
lottie.pauseAnimation()
lottie.setMinAndMaxFrame(lastFrame, lastFrame)
lottie.progress = 1.0f
// wait around a bit to see if my listeners detect any movement, then quietly make my getaway
lottie.postDelayed({
lottie.removeAnimatorListener(this)
lottie.setMinAndMaxFrame(1, lastFrame)
}, 500L)
}
}
}