I have a simple animation that makes a view go from one side of the screen to the other and its defined in the anim folder as left_to_right.xml
:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="true">
<translate
android:fromXDelta="-300%" android:toXDelta="360%"
android:fromYDelta="0%" android:toYDelta="0%"
android:duration="3200"/>
</set>
What I want is to have multiple views sliding across the screen at the same time but different speeds, so I have 2 more xmls called left_to_right_fast.xml
and left_to_right_slow.xml
which are the exact same except for a different duration.
So in my view class I have these methods to create a image of a stripe and animate it, and when the animation is done, I remove it and make another:
private fun doAStripe() {
if (!isRunning) return
val stripe = makeStripe()
stripeHolder.addView(stripe)
stripe.animation.onAnimationEnd {
(stripe.parent as ViewGroup).removeView(stripe)
doAStripe()
}
stripe.animate()
}
private fun makeStripe(): AppCompatImageView {
val imageView = AppCompatImageView(context)
imageView.layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
imageView.setImageResource(listOf(R.drawable.cp_stripe_blue, R.drawable.cp_stripe_gray, R.drawable.cp_stripe_red).random())
imageView.clearAnimation()
imageView.animation = AnimationUtils.loadAnimation(context, listOf(R.anim.left_to_right, R.anim.left_to_right_fast, R.anim.left_to_right_slow).random())
imageView.x = width / 2f
imageView.y = (0..(stripeHolder.height)).random().toFloat()
return imageView
}
So when I just call doAStripe()
it works as expected, a stripe slides across the screen, and repeats.
But I want to be able to have multiple stripes going at the same time, so I try calling doAStripe()
three times in a row, but when I do that - the stripes all seem to animate across the screen the first time but when the reappear they don't move, sit still for a couple seconds then disappears and new stripes appear to replace them.
So it seems like the animation is happening since the onAnimationEnd
is getting called... but its not actually happening. Anyone know the reason for this?
Also my onAnimationEnd
is just this convenience extension:
fun Animation.onAnimationEnd(callback: () -> Unit) {
setAnimationListener(object : Animation.AnimationListener {
override fun onAnimationRepeat(p0: Animation?) {
}
override fun onAnimationEnd(p0: Animation?) {
callback()
}
override fun onAnimationStart(p0: Animation?) {
}
})
}
Update: Here is a git repo with a demo project showing the bug
you'll notice if you make onCreate only call doAStripe()
once it works great, but call it more than once - and it works well for a couple stripes then starts freezing the animations.