1

When I have first recycler view item on position 0 and then lets say 10 items get inserted on position 0 making first one go to position 10 recycler view scrolls to position 10. How to disable this functionality making recycler view stay on top?

I have a possible answer below, but it has disadvatanges. With this aproach recyclerview indeed will scroll to the top but only after scrolling to the end. And it's kinda annoying. Any one knows how to make it stay on top without going to the end?

3 Answers3

1

I had the exact same problem - for me when my LiveData<List<Item>> which my recyclerview was displaying updated in such a way that the first item changed positions, it would always scroll to the new position of that item (but not if any other item other than the first one was moved). I found a relatively simple solution. In the fragment with the recylcerview which displays your LiveData, you presumably have code something like this:

myViewModel.getAllItems().observe(getViewLifeCycleOwner(), items -> {
   myAdapter.setItems(items);
});

To stop it from scrolling when the first item is moved, simply add these two lines either side of the setItems() method:

myViewModel.getAllItems().observe(getViewLifeCycleOwner(), items -> {
   Parcelable recyclerViewState = myRecyclerView.getLayoutManager().onSaveInstanceState();
   adapter.setItems(slItems);
   myRecyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
});

This seems to restore the original scroll position if it was going to change it, making the UI stay at whatever scroll position it was at before the change occurred without any perceptible movement.

Trex
  • 108
  • 9
0

One workaround is to register AdapterDataObserver on your recycler view adapter overriding onItemRangeInserted method as in the following code. When something gets inserted on position 0 it automatically triggers layoutManager to scroll to start of the list.

With this aproach recyclerview indeed will scroll to the top but only after scrolling to the end. And it's kinda annoying. Any one knows how to make it stay on top without going to the end?

adapter?.registerAdapterDataObserver(object: RecyclerView.AdapterDataObserver() {
                override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
                    if (positionStart == 0) layoutManager?.scrollToPosition(0)
                }
            })
0

Inspired by Константин Семочкин I found an easy solution:

listAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
    // Prevent the list from scrolling when an item position change
    override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
        lifecycleScope.launch {
            binding.manutenzioniList.scrollToPosition(fromPosition)
        }
    }
})

Every time that an item is moved the list moves back to the previous position. Note that the list do no start the smooth scroll at all, so there isn't any annoying scroll back and forth