1

I am making a movie list with RecyclerView and ConcatAdapter.

The ConcatAdapter consists of three different adapters, HeaderAdapter, MovieAdapter and FooterAdapter.

HeaderAdapter - displays either of progress bar, load error, or normal header. Its ViewType is different from the one for MovieAdapter.

MovieAdapter - It extends ListAdapter and displays movies with paging.

FooterAdapter - displays either of a progress bar, load error, or normal footer. Its ViewType is different from the one for MovieAdapter.

They all set up like this

recyclerView.adapter = ConcatAdapter(
        ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build(),
        headerAdapter,
        movieAdapter,
        footerAdapter
)

The issue is that the scroll position jumps to the top when users scroll up, reach to the top, load more movies and prepend the newly fetched movies with ListAdapter's submitList() But I want to keep the current position not jumps to the top.

Let me break down the problem scenario

  1. I have 50 movies {100, 101, .... 150} in the RecyclerView and they are already displayed

  2. I scroll all the way up to the top and now see the progress bar that is displayed by the HeaderAdapter

  3. I load 50 more movies {49, 50, 51, ... 99} and prepend them to the list as followings

    val temp = mutableListOf<Value>()
    val newMovies = loadMoreMoviesFrom(lastMovieId)
    
    temp.addAll(newMovies)
    // temp = {49, 50, 51, .... 99}
    
    temp.addAll(currentList)
    // temp = {49, 50, 51, .... , 99, 100, 101, ..... 150}
    
    submitList(temp)
    
  4. Then the list does not keep the current position but jumps to the top which shows the progress bar (Header) and 49, 50 as per the gif below. But I want to keep the position as it is.

enter image description here

But if I APPEND new movies in the same way as I did for prepeding, it actaully works as expected

Let's say I have 50 movies {0, 1, 2, ... 49}, scroll all the way down to the bottom, see the progress bar displayed by FooterAdapter, load more 50 movies {50, 51, .... 100}, append them to the list and submit. Then the list keeps the current position as per the gif below

enter image description here

I know I can use Android paging library 3 but I do have some reason why I want to paginate on my own and I don't want to explain it here because it's not the question.

The method to load another 50 chunks, prepend and submit is called from RecyclerView.OnScrollListener() when the scroll position reaches the end. I just took the part only and put it here for easy understanding.

So why the list jumps to the top when I prepend but stays at the current position when I append. How can I prevent the list from jumping to the top when I prepend?

Thank you guys and hope the gifs are of any help

KisungTae
  • 95
  • 1
  • 7

2 Answers2

0

As i understand, your response is a chunk of 50 items, and every time you scroll down, you request another chunk of 50 item simply if you make it manually, it won't be efficient whatever the workaround that you will do, so google offers a library it's called pagination which matches your case

check the documentation of paging library, there is a codelab that explains every step you need and if you want to make it manually, you can trace the scroll position of the recycler view by implementing the addOnScrollListener method, and every time you request a new chunk, scroll to the last position but I don't recommend that way, I prefer to use a pagination

Ahmed Nobi
  • 26
  • 2
  • Thank you for your suggestion. There is some reason why I want to implement pagination on my own but not use the Android paging library. The call for loading another 50 chunk is triggered from RecyclerView.OnScrollListener() not manually. – KisungTae Aug 16 '22 at 23:15
0

\ in class level

var position = -1 //inital value in first chuck

var totalScrollAfter = 0

in onscollChangedLisener method
position = item.posion
you can get it from the adapter of recycler view, last position which is here 49, and it will be 98 ,... and so on

totalScrollAfter = recyclerView!!.computeVerticalScrollOffset()

// when you request another chunk, and the request is ready to be submitted using

if (postion > -1) { recyclerView.scrollBy(0, totalScrollAfter) }

Ahmed Nobi
  • 26
  • 2