2017-04-17 96 views
5

如果我們使用DiffUtil.Callback,並做Diffutil在recycleview,使其自動滾動,如果一個新項目添加

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

我們如何能確保新元素的加入將滾動到新的位置。

我有一種情況,我看到項目消失,並創建一個新的第一個元素在頂部,但不可見。它隱藏在頂部,直到您向下滾動以使其可見。 在使用DiffUtil之前,我手動實現了這個功能,在知道自己正在插入某個位置(頂部)後,我可以滾動到該位置。

+1

只需添加項目並使用'RecyclerView.scrollToPosition(int position)'。當我不得不這樣做時,即使使用DiffUtil也是如此。 –

回答

7

您也有一個dispatchUpdatesTo(ListUpdateCallback)方法。

所以你可以只實現一個ListUpdateCallback它給你的第一個元素插入

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); 
    } 
} 

,然後只需滾動RecyclerView手動

myCallback.bind(adapter) 
adapter.setItems(itemList); 
diff.dispatchUpdatesTo(myCallback); 
recycler.smoothScrollToPosition(myCallback.firstInsert); 
+0

注意:即使開始之前不可見,它也會滾動到第一個位置。爲了獲得更好的用戶體驗,您應該嘗試保留用戶當前的滾動位置,並且只有在更新前可以看到開始時才滾動到開始位置。 –

+0

感謝分享! – Sevastyan

+0

@LorneLaliberte你能提供你的建議的代碼示例嗎?我認爲這將是最好的解決方案 – Konrad

9

有一個簡單的方法來做到這一點,還保留了用戶的滾動位置如果項目插入可視區域外:

import android.os.Parcelable; 

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

使用這種方法,如果將新項目插入到用戶可以看到它們的位置,則新項目將變爲可見 - 但如果項目插入視圖之外,則會保留用戶的視點。

相關問題