RecyclerView scrolls to top on notifyDataSetChanged in chat screen RecyclerView scrolls to top on notifyDataSetChanged in chat screen android android

RecyclerView scrolls to top on notifyDataSetChanged in chat screen


I think you shouldn't use onBindViewHolder that way, remove that code, the adapter should only bind model data, not listen scrolling.

I usually do the "onLoadMore" this way:

In the Activity:

private boolean isLoading, totallyLoaded; //RecyclerView mMessages;LinearLayoutManager manager;ArrayList<Message> messagesArray;MessagesAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    //...    mMessages.setHasFixedSize(true);    manager = new LinearLayoutManager(this);    manager.setStackFromEnd(true);    mMessages.setLayoutManager(manager);    mMessages.addOnScrollListener(new RecyclerView.OnScrollListener() {        @Override        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {            super.onScrolled(recyclerView, dx, dy);            if (manager.findFirstVisibleItemPosition() == 0 && !isLoading && !totallyLoaded) {                onLoadMore();                isLoading = true;            }        }    });    messagesArray = new ArrayList<>();    adapter = new MessagesAdapter(messagesArray, this);    mMessages.setAdapter(adapter);}@Overridepublic void onLoadMore() {    //get more messages...    messagesArray.addAll(0, moreMessagesArray);    adapter.notifyItemRangeInserted(0, (int) moreMessagesArray.size();    isLoading = false;}

This works perfeclty for me, and the "totallyLoaded" is used if the server doesn't return more messages, to stop making server calls. Hope it helps you.


You see, it's natural for List to scroll to the most top item when you insert new Items. Well you going in the right direction but I think you forgot adding setReverseLayout(true).

Here the setStackFromEnd(true) just tells List to stack items starting from bottom of the view but when used in combination with the setReverseLayout(true) it will reverse order of items and views so the newest item is always shown at the bottom of the view.

Your final layoutManager would seems something like this:

        mLayoutManager = new LinearLayoutManager(getActivity());        mLayoutManager.setReverseLayout(true);        mLayoutManager.setStackFromEnd(true);        mRecyclerView.setLayoutManager(mLayoutManager);


This is my way to avoid scrollview move to topInstead of using notifyDataSetChanged(), I use notifyItemRangeChanged();

List<Object> tempList = new ArrayList<>();tempList.addAll(mList);mList.clear();mList.addAll(tempList);notifyItemRangeChanged(0, mList.size());

Update:For another reason, Your another view in the top is focusing so it will jump to top when you call any notifies, so remove all focuses by adding android:focusableInTouchMode="true" in the GroupView.