Scroll while scrolling

Note: it my first post in English, i encourage you to criticize to improve my writing skills. Thanks beforehand.

Recently i was challenged to put scrolling container inside RecyclerView, so user would scroll while scrolling (¯\_(ツ)_/¯ yeah it sounds hilarious).

Starting from writing a layout for a custom ViewHolder and thinking whether it would works out of box with RecyclerView, remember that it was a bottleneck in ListView.

As you might guess, it didn’t work, all touch events that was dispatched to RecyclerView were consume by itself, so NestedScrollView didn’t get anything, so here comes the question: how can we forward touch events that belongs to scrolling view?

Android Team did a great job with RecyclerView, easy in extension with their powerful API for everything and of them is to intercept touch events before it will be considered as RecyclerView’s own scrolling behavior.

RecyclerView.OnItemTouchListener — is useful for application’s that wants to implement various forms of gestures for item view’s

Which touches we should intercept for ScrollView?

Not all touches are belongs to it, only if they are in the bounds of ScrollView. While all touches comes relatively to RecyclerView’s coordinates, we need to check whether they are in ScrollView

Intercepting touch events using OnItemTouchListener

From android developer documentation View’s (left, top, right, bottom) properties return

These methods return the location of the view relative to its parent

While parent of our ScrollView isn’t RecyclerView (and it is root view, in my example). Therefore we need to offset view bounds to RecyclerView’s coordinates, here comes 2 great methods:

ViewGroup#offsetDescendantRectToMyCoords — offset a rectangle that is in a descendant’s coordinate space into our coordinate space.

View#getGlobalVisibleRect() — return coordinates in r in global (root) coordinates

And it’s done, last thing to don’t forget to add/remove listener, it’s better to listen on onViewAttachedToWindow(VH holder) and remove it on onViewDetachedFromWindow(VH holder)