Reputation: 639
I added on click animations on some button items from a recycle view.
Everything works smoothly, however when I scroll down the list some buttons appear in a weird state like they were frozen during the animation phase even though the animation was not being triggered for these buttons while for others the their view is set to invisible/gone.
This is part of the shrinking animation code, where shrink is a ValueAnimator object.
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
}
}
I have a View
and ViewHolder
class where I bind the visibility of the recycle view items when I scroll.
Is there a step I missed in the animation lifecycle to work together with the recycle view items? I was thinking that maybe I have to take care of onAnimationStop
or onAnimationPause
cases but I am not sure.
Any help would be much appreciated.
Upvotes: 2
Views: 2030
Reputation: 2061
You can use setHasTransientState
to mark view as a kind of "dirty", so RecyclerView will not re-use it while animation is not finished. This should solve your issue. Here is the modified code:
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
}
}
This is exactly what PropertyAnimation do under the hood. Hope this will help :)
Upvotes: 2
Reputation: 2527
Start by removing the default RecyclerView
item animator
recyclerView.setItemAnimator(null);
And also cancel any custom running animation in the adapter onViewRecycled
Upvotes: 0
Reputation: 8575
I think that the cause of your problem is the fact that the views are recycled when you scroll. If the animation is triggered on a view and the list is scrolled the animation continues, but at some point, the view gets recycled and re-populated and it leads to the weird state.
The solution is to cancel the animation and set the initial state to the view in onBindViewHolder
method of your adapter.
The steps I would do in your case:
Upvotes: 12