RecycleView项目上的Android动画问题

时间:2018-05-16 05:48:06

标签: android animation android-recyclerview kotlin

我在循环视图中的某些按钮项上添加了点击动画。

一切顺利,但是当我向下滚动列表时,一些按钮出现在一个奇怪的状态,就像它们在动画阶段被冻结一样,即使没有为这些按钮触发动画,而对于其他按钮,它们的视图设置为不可见/不见了。

这是缩小动画代码的一部分,其中shrink是ValueAnimator对象。

shrink.addUpdateListener { animation ->
        val animatedValue = animation.animatedValue as Int
        v.layoutParams.width = animatedValue
        v.requestLayout()
    }
    shrink.addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationStart(animation: Animator) {
            super.onAnimationStart(animation)
            v.visibility = View.VISIBLE
            v.isEnabled = false
        }
        override fun onAnimationEnd(animation: Animator) {
            super.onAnimationEnd(animation)
            v.layoutParams.width = 0
            v.visibility = View.GONE
            v.isEnabled = false
        }
   }

我有一个ViewViewHolder类,我在滚动时绑定了回收视图项的可见性。

我是否在动画生命周期中错过了与循环视图项目一起工作的步骤?我在想,也许我必须照顾onAnimationStoponAnimationPause个案,但我不确定。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:10)

我认为问题的原因是滚动时视图会被回收。如果在视图上触发动画并且滚动列表,则动画继续,但在某些时候,视图会被回收并重新填充,从而导致奇怪的状态。

解决方案是取消动画并将初始状态设置为适配器的onBindViewHolder方法中的视图。 我将采取的步骤:

  1. 将您的价值动画师链接到视图持有者,因此每个视图持有者都有自己的值动画师。
  2. 使用视图持有者的本地值动画师,像现在一样触发动画。
  3. Cancel您的价值动画师onViewRecycled
  4. onBindViewHolder中明确将您的视图的可见性设置为可见,启用它并设置全宽。

答案 1 :(得分:0)

首先删除默认的RecyclerView项动画

recyclerView.setItemAnimator(null);

并且还取消适配器onViewRecycled

中的任何自定义运行动画

答案 2 :(得分:0)

您可以使用setHasTransientState将视图标记为一种“脏污”,因此RecyclerView不会在动画未完成时重新使用它。这应该可以解决您的问题。这是修改后的代码:

shrink.addUpdateListener { animation ->
    val animatedValue = animation.animatedValue as Int
    v.layoutParams.width = animatedValue
    v.requestLayout()
}
shrink.addListener(object : AnimatorListenerAdapter() {
    override fun onAnimationStart(animation: Animator) {
        super.onAnimationStart(animation)
        v.setHasTransientState(true) // Mark view
        v.visibility = View.VISIBLE
        v.isEnabled = false
    }
    override fun onAnimationEnd(animation: Animator) {
        super.onAnimationEnd(animation)
        v.layoutParams.width = 0
        v.visibility = View.GONE
        v.isEnabled = false
        v.setHasTransientState(true) // "Return" it to the pool
    }

}

这正是PropertyAnimation在后台执行的操作。希望这会有所帮助:)