Animation does not play when startAnimation is called in onBindViewHolder of an existing view
See original GitHub issueDescribe the bug
When calling startAnimation
in a RecyclerView
’s onBindViewHolder
, the animation does not play. This issue was partially fixed in https://github.com/airbnb/lottie-android/issues/1324, but that fix only handles the case when the LottieAnimationView
is first created, and not when it is rebound with different data.
The cause of the issue appears to be that when onBindViewHolder
is called, the view is in an unusual state where it is attached to the window, but isShown
is false because it has no parent.
Steps To Reproduce Here is a unit test that demonstrates the issue:
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/FragmentVisibilityTests.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/FragmentVisibilityTests.kt
index fc338b93..c48c684d 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/FragmentVisibilityTests.kt
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/FragmentVisibilityTests.kt
@@ -195,6 +195,51 @@ class FragmentVisibilityTests {
onView(withId(R.id.animation_view)).check(matches(isAnimating()))
}
+ @Test
+ fun testRecyclerViewCanAutoPlayInOnBindRebind() {
+ class TestFragment : Fragment() {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return RecyclerView(requireContext()).apply {
+ layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
+ // Setting itemAnimator to null is important for this test in order to
+ // prevent the recyclerview from creating an additional viewholder for the
+ // purposes of animation.
+ itemAnimator = null
+ adapter = object : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ return object : RecyclerView.ViewHolder(LottieAnimationView(parent.context).apply {
+ id = R.id.animation_view
+ setAnimation(R.raw.heart)
+ IdlingRegistry.getInstance().register(LottieIdlingResource(this))
+ }) {}
+ }
+
+ override fun getItemCount(): Int = 1
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ (holder.itemView as LottieAnimationView).apply {
+ // Cancel first, then play. This prevents the animation from
+ // carrying over from the initial binding.
+ cancelAnimation()
+ playAnimation()
+ }
+ }
+ }
+ }
+ }
+ }
+
+ val fragmentScenario = launchFragmentInContainer<TestFragment>()
+ // I wasn't able to figure out exactly what was needed to create an idling resource.
+ // Waiting for [RecyclerView.doOnLayout] was insufficient.
+ Thread.sleep(500)
+ fragmentScenario.onFragment { fragment ->
+ (fragment.view as RecyclerView).adapter!!.notifyItemChanged(0)
+ }
+ Thread.sleep(500)
+ onView(withId(R.id.animation_view)).check(matches(isAnimating()))
+ }
+
@Test
fun testDoesntAutoplay() {
class TestFragment : Fragment() {
Issue Analytics
- State:
- Created 4 years ago
- Comments:10
Top Results From Across the Web
android - How to animate RecyclerView items when adapter is ...
I am implementing the same thing but when i apply your answer or the accepted answer it doesnt work for me. for initial...
Read more >RecyclerView.ItemAnimator - Android Developers
This class defines the animations that take place on items as changes are made to the adapter. Subclasses of ItemAnimator can be used...
Read more >[Android Tips] 33. Lottie 在RecyclerView onBindViewHolder ...
Animation does not play when startAnimation is called in onBindViewHolder of an existing view · Regression: Animation does not play when ...
Read more >Intermediate RecyclerView Tutorial with Kotlin
In this RecyclerView tutorial you will learn how to build out intermediate techniques like swiping, animation and filtering in Kotlin.
Read more >Mastering Complex Lists with the Android RecyclerView
The idea of view recycling has been in Android since version 1 in the ... of the RecyclerView don't forget to add the...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I’m having the same issue described here and in #1284 My workaround for now is to use
post { icon.playAnimation() }
That seems to work but wondering if there’s a better solution.I re-checked the test in the description (thank you for that) after landing https://github.com/airbnb/lottie-android/pull/1981 and the test now passes!