RecyclerView notifyDataSetChanged scrolls to top position
Asked Answered
B

11

29

when calling notifyDataSetChanged on RecyclerView it doesn't retain the scroll position and scrolls to top, is there any solution to retain it's scroll position?

Burgonet answered 11/3, 2015 at 17:40 Comment(5)
DON'T call notifyDataSetChanged() on the RecyclerView. Use the new methods like notifyItemChanged(), notifyItemRangeChanged(), notifyItemInserted(), etc...Misbegotten
I tried notifyItemRangeInserted(), but even that scrolls to the top. Any idea?Undercoating
As @XaverKapeller said , I have used notifyItemInserted(),notifyItemRangeInserted, it works properly without scrolling the listview to the top.Burgonet
@MohamedHatemAbdu what do you set into notifyItemInserted or notifyItemRangeInserted ?could you please explain your solution?Allegedly
Please look at this answer https://mcmap.net/q/176297/-recyclerview-scrolls-to-bottom-when-data-is-loadedGeorgiannegeorgic
J
19

If your RecyclerView list item parent has "wrap_content" property, Recyclerview calculates the heights again and scrolls top.

There are two solutions:

  1. Set your height a constant value like this: layout_height="100dp"
  2. Use StaggeredGridLayoutManager like this:

    mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL));

The second solution is more efficient and I suggest this one

Jeremiad answered 29/5, 2016 at 13:22 Comment(1)
Yes, Recycler view calculates height in case of "wrap_content" so fix is setting fixed layout height or making height to "match_parent".Backfire
B
13

Not sure if this solves your problem but I was having the same issue and it was because I was calling setAdapter after notify. So, not calling setAdapter after notify solved the problem.

mAdapter.notifyItemRangeInserted(mAdapter.getItemCount(), list.size() - 1);
recyclerView.setAdapter(); // remove this line. 
//Do this only when you're setting the data for the first time or when adapter is null. 
Blau answered 8/2, 2016 at 9:14 Comment(0)
A
3

As I am guessing, what you are doing is resetting the adapter to the RecyclerView and then calling notifyDataSetChanged().

You need to pass only the dataList to the adapter by passing dataList in adapter method like adapter update(dataList). And in this method you can assign this list to adapter list like;

public void update(ArrayList<Hashmap<String,String> list){
  this.mList = list;
}
Antiphon answered 16/7, 2017 at 13:14 Comment(0)
J
2

notifyItemChanged() make the RecyclerView scroll and jump to UP

android:descendantFocusability="blocksDescendants"

Horizontal recyclerView inside vertical recyclerView generally causes that problem and this is best approach to get rid of problem. Don't put this attr into horizontal recyclerViews, it needs to be in only Parent (vertical RecyclerView).

Jagatai answered 9/5, 2020 at 2:41 Comment(0)
T
1

You can use swapAdapter() and after call notifyDataSetChange(). This works for me.

Tralee answered 20/11, 2015 at 13:39 Comment(0)
C
1

RecycleViews will scroll back to the top on any variant of notifyDataSetChanged if they don't have a layout manager. Here's an example of how to set one.

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(context, OrientationHelper.VERTICAL, false);
recycleView.setLayoutManager(linearLayoutManager);
Crimson answered 20/5, 2017 at 5:7 Comment(1)
can you please help with this one #58850410Embryologist
B
1

In my case, the recyclerview was paginated. Every time it reaches the end and loads/inserts item using notifyItemInserted, the recyclerView used to scroll. So following worked for me:

recycler_view.stopScroll();

As stated in the doc:

Stop any current scroll in progress, such as one started by smoothScrollBy(int, int), fling(int, int) or a touch-initiated fling.

Bedclothes answered 12/4, 2018 at 9:58 Comment(1)
My order was: 1 find target view's position 1.1 calc what position will have our view after inserting new data 2 save current view's top offset 3 swap adapter's data 4 call notifyDataSetChanged 5 call recyclerView stopScroll 6 call recyclerView scrollToPositionWithOffset with calced view's position and latest offsetHardnett
P
1

Use scrollToPosition() of recyclerView to scroll to the specific position. call this method after notifyDataSetChanged() by passing the length of adapter

arrayList.add(new ChatBotModalClass("aaaa","bbbb"));
adapter.notifyDataSetChanged();
recyclerview.scrollToPosition(adapter.getItemCount()-1);
Pilloff answered 31/5, 2023 at 5:32 Comment(0)
S
0

Use android:descendantFocusability="blocksDescendants" in the parent recyclerView . It will fix the issue. I had a child recyclerView inside the parent recyclerView and this trick helped me. Also except first time you should always use notifyDataSetChanged on the adapter.

Sachi answered 11/5, 2021 at 12:40 Comment(0)
T
-1

You can't scroll to position without having set the adapter first. Set your adapter first, even if your list is empty. Update your list when you get the data. Then call adapter.notifydatasetchanged() method. You can then scroll to the last position. Let me know if this answers your question or if I have to put an answer – mmmcho

Telfore answered 12/9, 2020 at 0:49 Comment(0)
G
-1

This worked for me:

Set the fixed size property on the RecyclerView to "true" which prevents scroll up after calling notifyDataSetChanged on the adapter:

mRecyclerView.setHasFixedSize(true)
Gyroplane answered 25/1, 2023 at 20:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.