我有一个简单的动画,使视图从屏幕的一侧转到另一侧,在动画文件夹中定义为 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>
我想要的是在屏幕上同时在屏幕上滑动多个视图,但速度不同,所以我有2个称为left_to_right_fast.xml
和left_to_right_slow.xml
的XML,除了不同的持续时间外,这是完全相同的。
因此,在我的视图类中,我有这些方法来创建条纹的图像并为其动画,当动画完成时,我将其删除并进行另一个方法:
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
}
因此,当我只调用 doAStripe()
时,它可以按预期工作,屏幕上的条纹滑动并重复。
,但我希望能够同时使用多个条纹,所以我尝试连续三遍拨打doAStripe()
,但是当我这样做时 - 条纹似乎是第一次在屏幕上进行动画他们不移动的重新出现,静止几秒钟,然后消失,新条纹似乎取代了它们。
因此,由于onAnimationEnd
被称为...但实际上并没有发生动画,因此动画似乎正在发生。有人知道这样做的原因吗?
我的onAnimationEnd
也只是这种便利扩展:
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?) {
}
})
}
更新:这是一个git回购,带有演示项目显示错误
您会注意到,如果您只能致电doAStripe()
,则一旦效果很好,但是将其称为多次 - 并且对几个条纹效果很好,然后开始冻结动画。
您要进行一些骇客来同时进行两个动画,但是我遵循您的存储库,我进行了测试,是的,它看起来很笨拙Handler
Android
中的Animation
将为您处理线程,并且您的实现存在一个问题,所有这些动画都在MainThread
上,这会导致Laggy。
所以我最终这样做了:
private fun doAStripe() {
val stripe = makeStripe()
stripeHolder.addView(stripe)
stripe.postDelayed({
(stripe.parent as ViewGroup).removeView(stripe)
doAStripe()
}, stripe.animation.duration)
stripe.animate().withLayer()
}
它看起来冰沙,但并不快,也许您可以用anim
文件控制它。
我还添加了withLayer()
它可以为您随后添加到动画的所有视图启用硬件动画。
还在您的makeStripe()
方法中添加了imageView.invalidate()
,以使ImageView
无效。有关更多信息,您可以在有必要在视图上执行无效
这是一个简单的演示:
https://vimeo.com/334493212
这不是最好的选择,但是,根本无法正确说明它的问题,因此,如果我有更多的时间我会更深入地检查一下,但是从现在开始,问题"冻结"已经消失了。