Diffutil in recycleview, making it autoscroll if a new item is added

后端 未结 3 1066
栀梦
栀梦 2021-01-01 14:00

If we use DiffUtil.Callback, and do

adapter.setItems(itemList);
diff.dispatchUpdatesTo(adapter);

how can we make sure that ad

相关标签:
3条回答
  • 2021-01-01 14:05

    You have a dispatchUpdatesTo(ListUpdateCallback) method to use as well.

    So you could just implement a ListUpdateCallback which gives you the first element inserted

    class MyCallback implements ListUpdateCallback {
        int firstInsert = -1;
        Adapter adapter = null;
        void bind(Adapter adapter) {
            this.adapter = adapter;
        }
        public void onChanged(int position, int count, Object payload) {
            adapter.notifyItemRangeChanged(position, count, payload);
        }
        public void onInserted(int position, int count) {
            if (firstInsert == -1 || firstInsert > position) {
                firstInsert = position;
            }
            adapter.notifyItemRangeInserted(position, count);
        }
        public void onMoved(int fromPosition, int toPosition) {
            adapter.notifyItemMoved(fromPosition, toPosition);
        }
        public void onRemoved(int position, int count) {
            adapter.notifyItemRangeRemoved(position, count);
        }
    }
    

    and then just scroll the RecyclerView manually

    myCallback.bind(adapter)
    adapter.setItems(itemList);
    diff.dispatchUpdatesTo(myCallback);
    recycler.smoothScrollToPosition(myCallback.firstInsert);
    
    0 讨论(0)
  • 2021-01-01 14:12

    I used RecyclerView.AdapterDataObserver to detect when new items were added, and then scroll to the top of my list;

    adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            recycleView.smoothScrollToPosition(0);
        }
    });
    
    0 讨论(0)
  • 2021-01-01 14:19

    There's an easy way to do this that also preserves the user's scroll position if items are inserted outside the viewable area:

    import android.os.Parcelable;
    
    Parcelable recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
    // apply diff result here (dispatch updates to the adapter)
    recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);              
    

    Using this approach, the new items are made visible if they are inserted where the user can see them -- but the user's viewpoint is preserved if the items are inserted outside of view.

    0 讨论(0)
提交回复
热议问题