对多个视图进行动画处理会导致动画冻结

时间:2019-05-03 18:19:15

标签: android xml animation kotlin

我有一个简单的动画,它使视图从屏幕的一侧转到另一侧,并且在动画文件夹中将其定义为c

left_to_right.xml

我想要的是让多个视图同时在屏幕上滑动但速度不同,因此我还有2个名为<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> left_to_right_fast.xml的xml,它们完全相同,除了不同之处持续时间。

因此,在我的视图类中,我具有以下方法来创建条纹图像并对其进行动画处理,动画完成后,我将其删除并制作另一个图像:

left_to_right_slow.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() 3次,但是当我这样做时-条纹似乎都在整个屏幕上动起来了第一次,但当它们重新出现时不动时,请静坐几秒钟,然后消失,并出现新的条纹来代替它们。

所以好像动画正在发生,因为doAStripe()被调用了……但是实际上并没有发生。有人知道原因吗?

我的onAnimationEnd就是这个方便的扩展名:

onAnimationEnd

更新:Here is a git repo with a demo project showing the bug

如果您使onCreate仅在效果很好的情况下调用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?) { } }) } ,但会不止一次地调用它,则您会注意到它-在几个条纹上效果很好,然后开始冻结动画。

1 个答案:

答案 0 :(得分:1)

您需要做一点技巧来使两个动画同时运行,但是我很好地遵循了您的存储库并进行了测试,是的,它看起来很滞后,如果您将Animation控制在Handler Android将为您处理线程,而您的实现存在一个问题,所有这些动画都在MainThread上,这会导致延迟。

所以我最终这样做了:

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()

  

它为随后添加到动画中的所有视图启用硬件动画。

还在您的imageView.invalidate()方法中添加了makeStripe(),以使ImageView无效。有关更多信息,您可以阅读此When it's necessary to execute invalidate on a view

这是一个简单的演示,外观:

https://vimeo.com/334493212

这不是最好的选择,但是,它本身的问题根本无法正确说明,因此,如果我有更多时间,我会更深入地检查一下,但是从现在开始,“冻结”。