· 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.
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 GridLayoutAnimation
s 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
orrandom
. - direction: it specifies how the items appear based on the column delay:
top_to_bottom
,left_to_right
,bottom_to_top
, andright_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.