Achieving smooth scrolling in a scrolling layout containing a RecyclerView

Nnabueze Uhiara
3 min readMar 10, 2019

--

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:

jerky scroll

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:

  1. Disable nestedScrolling in recyclerview
  2. 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:

with recyclerview nestedScrolling disabled

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

showing a list of 1000 items makes the page lag

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:

  1. A header item layout, consisting of all views that should be above the recyclerview main items.
  2. The main item layout
  3. 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:

new layout design just contains recyclerview
views above the recylerview in the previous design now moved to a header item layout
views below the recyclerview in the previous design now moved to a footer item layout
Recyclerview adapter with the header and footer pattern applied

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.

set dummy placeholders for the header and footer

And we are done! You have your smooth scrolling list that also allows item recycling.

final result using the header — footer pattern

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.

--

--