89 lines
2.9 KiB
Kotlin
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)
|
|
}
|
|
}
|
|
} |