In the project I was recently working on I was asked to implement a list with item animations upon their entrance on and exit from screen. The animations would play when the item view entered or exited the zone in the top, or the bottom of the view. In this article I will outline how I implemented this effect and how you can also do this in your application using your code, or the simple library I wrote to achieve this effect.
To accomplish our goal we would need to access RecyclerView’s children in its onScrolled method to start entrance or exit animation. For that we could create AnimatedRecyclerView class that extends RecyclerView. Then, in
onScrolled we could check whether the views should be animated.
Now we need to implement methods that would check if the view did enter or exit the screen. To do that we need to check whether top or the bottom of the item view has crossed a border from the top of the screen.
As you can see in the above picture we need to check whether bottom of the item view changed their y coordinate from lesser than the y position of the animation margin line to the one larger than that. That way we could figure out if the view has entered the screen from the top. We can express it in code as:
bottom >= topMarginY && bottom + dy < topMarginY
bottom is y coordinate of the bottom of the item view,
topMarginY is y coordinate of the top margin line and
dy is amount scrolled.
The first part of the expression checks whether the bottom of the item view is below margin line after scroll, the second on — whether it was above before the scroll.
In a similar fashion we can check if the top of the view crossed the bottom margin line during a scroll:
top >= bottomMarginY && top + dy < bottomMarginY
With those two expressions we can figure out if the view has entered or exited the ScrollView during scroll down. To complete the solution we now need to add checks for scrolling up. For exiting to the top of the screen we can use expression:
bottom <= topMarginY && bottom + dy > topMarginY
and for entering from the bottom of the screen:
top <= bottomMarginY && top + dy > bottomMarginY
We can now combine those expressions to implement the methods in our AnimatedRecyclerView class:
This basic implementation allows us to animate views that are scroll into the screen, and scroll out of it. The downside is the animations will apply to all of the views in the RecyclerView — we can’t really differentiate between them easily, and for each list with different animations we need different AnimatedRecyclerView implementation.
To improve upon the basic solution we can move the animation to the ViewHolders used by the RecyclerView’s Adapter. To implement that, however, we need to gain access to the instances of view holders associated with the item views currently visible in the RecyclerView. The class itself does not provide a method to access those view holders, so some additional code is required.
First we need to create an abstract implementation of ViewHolder with the callback methods needed to inform it of the events related to its view entering or exiting the screen. You might notice that separate callbacks for the top and bottom of the screen events were created, so different animations could be applied.
Next we need to add a list of view holders associated with item views currently added to the recycler view, and methods for adding and removing elements to that list.
The methods we added in AnimatedRecyclerView have to be called by our adapter implementation, as it has the callback methods for the view attached and detached events.
Finally we can finish AnimatedRecyclerView implementation. The conditions for checking whether the views entered or exited top or the bottom of the screen can be split into different methods, and based on them we can run methods from AnimatedItemHolder class.
With those improvements we can easily reuse the code we wrote by using our AnimatedRecyclerView in our views, and extending AnimatedRecyclerAdapter and AnimatedItemHolder.
As you see this implementation has only one view holder and uses the same animation for items entering from and exiting to both top and bottom of the screen. However, nothing stops us from implementing few different view holders for different view types, and implementing different animations for top and bottom of the screen.
You can find complete implementation with example usage here: https://github.com/codequest-eu/AnimatedRecyclerView . If you have any ideas on how this code could be upgraded, let me know. Happy coding!