· 3 min read

Layout animations on RecyclerView

Since Material Design was presented, I’ve been amazed by the animations some videos showed when populating a grid. If you haven’t seen it, it consists of a diagonal animation that populates the activity from top to bottom and from left to right. Really nice.

layout_animation_recyclerview

I’ve been trying all the alternatives to get that behaviour. One solution, that a lot of people mentions, is to use the RecyclerView::notifyItemInserted() method. But this method doesn’t give much control about the order of animation, so didn’t seem like a good solution. Another one, which in fact works, consists of animating the elements in onBind() only when necessary. But the code is rather delicate and intrusive (we are adding animations inside the adapter). It’s really difficult to make it work properly.

Layout animations to the rescue!

In the end, the solution was simpler than expected. I must admit I haven’t used layout animations much, so this option didn’t come up to my mind instantly. But when looking for solutions, I found this awesome gist from Musenkishi that gave me the solution. The problem is that RecyclerView doesn’t use layout animations by default, but this code makes it able to use GridLayoutAnimations as a GridView would do. This is the mentioned gist:

Configuring the Layout Animations

The good thing about layout animations is that we can define them and assign them through XML, so our code is not altered by the inclusion of the animation. We just need to define an XML with the corresponding layout animation:

<gridLayoutAnimation 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:columnDelay="15%"
    android:rowDelay="15%"
    android:animation="@anim/slide_in_bottom"
    android:animationOrder="normal"
    android:direction="top_to_bottom|left_to_right"/>

We can customize the animation as we prefer:

  • columnDelay / rowDelay: the percent of the time the elements of the rows and columns will be delayed when animating them. That way we can specify that the next views in the row and the column are animated one after the other, instead of appearing all of them at the same time.
  • animation: the animation that will be used to make the views appear in the screen. I’m using an animation that slides in from the bottom of the screen.
  • animationOrder: It can be normal, reverse or random.
  • direction: it specifies how the items appear based on the column delay: top_to_bottom, left_to_right, bottom_to_top, and right_to_left are the possible values.

This is the XML of the slide in animation:

<translate 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:fromYDelta="100%p"
    android:toYDelta="0"
    android:duration="@android:integer/config_mediumAnimTime"/>

Tweaking the animation timing

If you just execute like this, you’ll see that while the app is opening, the layout animation is executed, so you can’t really see the animation taking effect. For versions previous to Lollipop you can’t do much, there is not (or at least I didn’t find) an effective way to know when the enter transition finished. But from Lollipop, we can use onEnterAnimationComplete to check that. So, in onCreate, if the SDK version is older than Lollipop, the RecyclerView is populated:

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { 
    setRecyclerAdapter(recyclerView); 
}

In Lollipop and newer, onEnterAnimationComplete will be called. Time to populate the RecyclerView and request a new layout animation:

@Override 
public void onEnterAnimationComplete() { 
    super.onEnterAnimationComplete(); 
    setRecyclerAdapter(recyclerView); 
    recyclerView.scheduleLayoutAnimation(); 
}

Conclusion

You could easily tweak this layout animation to create some alternative enter animations. Play around with the animation configuration and see what you can get.

The code of this example is included in Materialize your App repository at Github.

    Share:
    Back to Blog