Saving Scroll Positions of Nested RecyclerViews

Joey Tan
AndroidPub
Published in
2 min readMay 3, 2019

--

One of the most annoying things when using RecyclerViews is that by nature they don’t store item states upon recycling. Thus, each item resets to its original state from creation as soon as you scroll away from the view. And the issue with nested RecyclerView carousels is that each carousel loses the index that was scrolled to originally. Makes you wonder, is there a trend being practiced in over-the-top apps like Netflix, Prime Video, Disney+, or even Google Play Store? The answer is yes.

Storing the carousel states

The idea behind this solution is that we will save the current scroll index of each horizontal carousel in some data structure before it is recycled. This way when the views return to foreground we can retrieve the saved indices and set the scroll positions for the carousels.

Few things to consider:

  • All changes should be done in the outer adapter.
  • We should store a LinearLayoutManager in the view holder and instantiate it upon creating its inner RecyclerView.
  • Fun fact: you can get the parent context in an adapter without passing it to the constructor inside onCreateViewHolder with mContext = viewGroup.getContext()
  • Create a SparseIntArray or map to hold the scroll position of each carousel.

Now override the onViewRecycled to store the position of the first visible item in that carousel after the view holder recycles.

Retrieving carousel states

Now that the states are stored we can retrieve them dynamically in onBindViewHolder per position.

We have now just created an adapter that maintains the states of a carousel when it is recycled through the list! Although this solution works best when SnapHelper is used for the carousel, since the positions closest to the first visible item is used as a reference point. This technique can be used to store and retrieve data and complex views with similar list patterns.

Hope this helps!

--

--

Joey Tan
AndroidPub

Software Engineer at Sony Pictures Entertainment