问题
If we use DiffUtil.Callback
, and do
adapter.setItems(itemList);
diff.dispatchUpdatesTo(adapter);
how can we make sure that adding of new elements will scroll to that new position.
I have a case where I see item disappear, and a new one is created as a first element at the top, but not visible. It is hidden on top until you scroll down to make it visible.
Before using DiffUtil
, I was implementing this manually, and after I knew I was inserting at some position (on top) I could scroll to.
回答1:
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);
回答2:
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.
回答3:
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);
}
});
来源:https://stackoverflow.com/questions/43458146/diffutil-in-recycleview-making-it-autoscroll-if-a-new-item-is-added