Achieving smooth scrolling in a scrolling layout containing a RecyclerView
You have probably had times (or maybe this is that time) when you had to embed a Recyclerview in a layout containing other views and you wanted to whole layout to scroll.
For most, the first instinct is to use a Recyclerview to display the list data and then wrap the entire layout with a Scrollview, since you want the whole page to scroll. Like this:
This might seem right but it actually is not: the scrolling behaviour leaves much to be desired. See gif below:
Observe closely, the scroll is not smooth, it drags. This is not the behaviour we want, the scrolling motion should mimic the speed with which the user flings through the page.
I know of two(2) ways to achieve smooth scrolling of the entire layout:
- Disable nestedScrolling in recyclerview
- Use the recyclerview header/footer pattern
TLDR use the second method, the first is inefficient.
Disable Recyclerview NestedScrolling method
This method is pretty straightforward:
The result:
The result is a perfect and smooth scroll but this method disables view recycling which creates a bigger problem: as the list size grows, the page starts to lag due to too many view inflation.
With view recycling, Recyclerview only needs to inflate the number of views that will fill the screen and 2 extra (one at either end) for smooth scrolling. As a user scrolls, any item view that goes out of view is used to show items that are to come into view. That way, if it takes 8 items to fill a screen, then at most 10 items will be inflated no matter the size of the list being shown.
Without view recycling, the number of views inflated = number of items in list. This is very inefficient. The gif below is the result of loading 1000 items using this method. Notice how it impacts app start-up time
Tip: Add a breakpoint in onBindViewHolder() or onViewRecycled(); if it is called each time items scroll off screen and new items come into view, then itemViews are recycled
Recyclerview header/footer pattern
This will require you to re-structure your layout design. The main layout will now contain just a recyclerview. The itemLayout to be passed to this recyclerview adapter will be of 3 kinds:
- A header item layout, consisting of all views that should be above the recyclerview main items.
- The main item layout
- A footer layout, which is made up of all views that should be below the recyclerview main items.
The step-by-step code is shown below:
Finally, you have to set dummy items in the list to mark the header and footer positions. In this example, I want the header and footer to be the first and last items respectively so the header dummy items will be in positions 0 and lastIndex. If your header and footer require dynamic content, this is a good place to pass them across.
And we are done! You have your smooth scrolling list that also allows item recycling.
If you are confused by the <layout> and binding you see in the code snippets, read up on dataBinding, it’s actually easy and I love using it.
Feel free to drop in comments, questions and suggestions; let me know how you do yours especially if yours is better. You can also reach out to me on Twitter.
If you enjoyed this/ found it helpful, please clap 👏 away to indicate.