Adapter / LinearLayoutManager / RecyclerView

Scrolling RecyclerView – Part 1

In this series of articles we’ll take a look in to scrolling behaviour of RecyclerView, and discover some oddities that may crop up, and some options for fixing them.

Recently I encountered some strange behaviour when using smoothScrollToPosition() on RecyclerView. So let’s start by creating a simple RecyclerView-based project to demonstrate the problem.

Let’s start with a layout containing a single RecyclerView:

Next a menu containing a couple of actions:

There are also a couple of VectorDrawable icons (menu_up and menu_down) which I haven’t listed here, but are available in the source.

We also need a simple Adapter for our RecyclerView which will create a large list of 1000 simple list items:

I won’t bother with an explanation of this as there’s nothing in here which hasn’t already been covered in Material – Part 5.

Finally we hook this all up in our main Activity class:

So what we’ve created here is a RecyclerView using a LinearLayoutManager with an Adapter of 1000 very simply list items. Then we have two menu actions which will perform a smooth scroll to the top and bottom of the list.

This is all pretty straightforward stuff.

But if we try this out, we begin to see the problem:

If we scroll a small distance down and then hit the “go to top” action everything is fine. However if we’re at or near the top and hit the “go to bottom” button then it certainly scrolls smoothly to the bottom but actually takes around seven second to get there. This is far too long to keep the user waiting and would result in some very frustrated users if we were to include this behaviour as-is in a real app.

My initial thought when I saw this behaviour is that there must me a simple setting somewhere which would speed up the scroll speed. However that proved not to be the case because there is an awful lot more going on here than is immediately apparent.

In the next article we’ll have a deep explore of how this scrolling is actually performed so that we may fully understand the why it isn’t possible to have a simple setting to change the scroll duration.

The source code for this article is available here.

© 2015, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 Scrolling RecyclerView – Part 1 by Styling Android is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Permissions beyond the scope of this license may be available at http://blog.stylingandroid.com/license-information.

8 Comments

  1. This is one of the components in RecyclerView where I wish we had more control on. I managed to use a custom Interpolator and set a different scrolling speed, but the code doesn’t look pretty at all :/

  2. Great article!

    recyclerView.smoothScrollToPosition(recyclerView.getAdapter().getItemCount());

    Should not it be getItemCount() – 1 ?
    If you tried using scrollToPossition(), it doesn’t work unless you decrement the item count by one.
    I think it would be more consistent to decrement it here too.
    Correct me if I’m wrong

    Cheers

  3. Great post man, conrgatulations.
    It helped me a lot, but I still have som issues with smoothScroll, the thing is that I am using smoothScrollBy(x,y), and i am passing the method the width of my next view, every view has the same width not even a dp of difference, but sometimes the method does not scroll the appropriatte distance.
    Do you have an idea why this is happening??

  4. public static ViewHolder newInstance(View itemView) {
    TextView textView = (TextView) itemView.findViewById(android.R.id.text1);
    return new ViewHolder(itemView, textView);
    }

    In above method, in which xml file contains the view – text1 ? . There is no such control called text1

    1. Yes there is. It is in the layout inflated in onCreateViewHolder(): android.R.layout.simple_list_item_1 which is a standard system layout, hence the use of android.R prefix rather than accessing resources in the local R.java

Leave a Reply

Your email address will not be published. Required fields are marked *