Custom Controls / RecyclerView

RecyclerView FastScroll – Part 2

In the previous article we got our FastScroller control framework in place. In this concluding article in this series we’ll add touch and scrolling behaviours.

The first thing that we need is an internal method which will be called in order to set the positions of both the bubble and handle whenever the scroll position changes either because of a touch event within FastScroller, or because the user scrolls the RecyclerView itself:

Theres a little bit of maths required here as the handle and bubble may be different heights and we need to handle each independently. When scrolling we want each have its top edge at the top when item 0 in the list is visible, and its bottom edge at the bottom when the final item in the list is visible.

getValueInRange() is a utility method which ensure that the bubble and handle always remain within their track.

Our FastScroller control is associated with a RecyclerView, and so the next task is provide a mechanism to make that association using a simple setter:

When the setter is called, is sets an OnScrollListener instance which gets called whenever the user directly scrolls the RecyclerView so that we can adjust the positions of the handle and bubble accordingly. There’s a little bit of logic required here to provide the correct positioning at the top and bottom of the list

The next thing we need to look at in our FastScroller control is handling touch events. The behaviour that we’re looking to implement is: When the user taps within the control, the handle will appear. The user can drag up and down to change the current position. When the user releases, then there will be a short delay before the handle is hidden again. This is implemented by overriding onTouchEvent():

When we receive a down or move action we set the current position to match the current Y position, cancel any animations which may be running, and any delayed handler callbacks (more on this in a second). If the handle is not visible then we call the method we created earlier to show it. Finally we set the current position of the RecyclerView before retuning true to consume the touch event.

When we receive an up action we use a Handler to post a delayed action to hide the handle after a short delay.

When we set the RecyclerView position we include a bit of logic to snap to the bottom if we’re within a certain distance of the bottom, or snap to the top if the first item is visible, otherwise we calculate the correct proportion value if we’re somewhere in the middle.

Note that we’re only using scrollToPosition() here and not smoothScrollToPosition() so we’ll have none of the issues covered in the previous series.

That’s our control complete. All that’s left is to connect it in. First we add it to the layout containing our RecyclerView:

Finally we need to create the association between RecyclerView and FastScroller:

That’s it. We can now see our fas scrolling behaviour:

One final note: In the Contacts app the FastScroller handle contains a letter indicating the current position within the list. This is using a slightly more complex Adapter than our example, but it should not be a massive amount of work to add this. Perhaps this is something that we’ll cover in a future post.

The source code for this series is available here.

© 2015, Mark Allison. All rights reserved.

CC BY-NC-SA 4.0 RecyclerView FastScroll – Part 2 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.

10 Comments

  1. I think the website to download the source code isn’t updated. It lacks the code you have here, and the last comment there is of “part 1” .
    Please update it, and also please show how to fix the location of the label-popup (the bubble) that is shown while you drag the scroller.

      1. There *is* no way it looks on Android 5.1 – it is not a control built in to the system, it is implemented differently by different apps.

  2. Sorry for my English, but o realy need help.
    I have next bag: when i move the fastscroller – he is twitches, twinkles. How it fix?

  3. Two doubts about all this:

    1) When I have few elements on my list (let’s say 50) and scroll recyclerview itself, the animation is not so fluid. Any Idea on how to make it better?

    2) When I change the number of elements on the list to 50 and scroll the list till the end, the bubble does not reach the end. Any idea why?

  4. Awesome tutorial. I was wondering if you were still thinking or planning to add the text to the bubble?

    Thanks, JP

Leave a Reply

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