4

我使用GridLayoutManager覆蓋getItemOffsets()方法(請參閱下面的代碼)將等於邊距應用於我的RecyclerViewItemDecoration覆蓋getItemOffsets()和動畫

但是,當從適配器中刪除一個對象時,將不調用偏移量來調用刪除動畫。因此,迴歸開始於與要移除的對象不同的位置。

我試圖通過getSpanIndex(position)得到的位置,但由於對象已經從適配器刪除,當getItemOffsets()被稱爲位置(parent.getChildAdapterPosition(view))返回NO_POSITION

有沒有辦法在我的情況下得到補償?

@Override 
public void getItemOffsets(Rect outRect, View view, 
        RecyclerView parent, RecyclerView.State state) { 

    GridLayoutManager mgr = parent.getLayoutManager(); 
    int position = parent.getChildAdapterPosition(view); 

    if (position == RecyclerView.NO_POSITION) { 
     // here I need to access the position of the current element 
     // and call outRect.set(left, top , right, bottom); 
     // which is not possible because it is no longer in the adapter 
     return; 
    } 

    int spanCount = mgr.getSpanCount(); 
    int spanSize = mgr.getSpanSizeLookup().getSpanSize(position); 
    int spanIndex = mgr.getSpanSizeLookup().getSpanIndex(position, spanCount); 

    if (spanIndex == spanCount-1) { 
     // last element 
     left = space/2; 
     right = space; 
    } else if (spanIndex == 0) { 
     // first element 
     left = space; 
     right = space/2; 
    } else { 
     // middle element 
     left = space/2; 
     right = space/2; 
    } 
    outRect.set(left, top, right, bottom); 
} 
+0

請您在移除物品時澄清您的問題嗎?如果你刪除一個元素,下一個元素動畫來填充空的位置,這究竟是不是工作? –

+0

對於RecyclerView中的元素,偏移量顯示正確(例如,最後一列中的元素左側20個像素,右側40個像素右側)。使用上面的代碼時,動畫由於位置== RecyclerView.NO_POSITION'而從方法返回,因此在沒有邊距的位置(0左和0右)開始。在這裏,我需要找出已刪除元素的位置(例如最後一列),以便爲平滑動畫應用正確的偏移量。 –

回答

3

嘗試使用視圖LayoutParams。如果您不使用一些自定義LayoutManager,它應該包含您需要的信息。

int position = ((RecyclerView.LayoutParams) view.getLayoutParams()).getViewAdapterPosition(); 
+0

非常感謝'LayoutParams'! 'getViewAdapterPosition()'沒有工作,但現在我使用'RecyclerView.LayoutParams.leftMargin'等來應用邊距而不是調用'outRect.set(left,top,right,bottom)',並且動畫與預期的一樣平滑! –

+0

@jeff_bordon你能解釋一下你是如何設法做到的。我明白了,但仍然存在邊距(或偏移量)實際應用於錯誤項目的問題 - 不是當前移除的項目,而是下一個,它仍在適配器中。 –

2

其實,從父母那裏得到孩子的位置是不好的決定。實際的視圖狀態可能與實際狀態不同,因爲同時工作或ItemDecorator,或LayoutManager或RecyclerView來對它們進行排序,或者適配器來更改某些元素的位置。

更好的方法,當要求Recycler給你ViewHolder某些視圖。然後你可以得到你需要的全部信息(getLayoutPosition(),getAdapterPosition())。

parent.getChildViewHolder(view).getLayoutPosition(); 
parent.getChildViewHolder(view).getAdapterPosition; 

而另一個建議,而不是你的情況。如果您需要獲取ItemCount,請不要使用adapter.getItemCount(),因爲在Adapter和Recycler中項目的數量可能會有所不同,所以最好從狀態獲取。

state.getItemCount() 
0

所以在試圖找出這一點後,我終於偶然發現了ViewHolder#getOldPosition

的Javadoc說以下內容:

當LayoutManager的支持動畫,RecyclerView道3點的位置爲ViewHolders執行動畫。

如果在先前的onLayout調用中佈置了ViewHolder,則舊位置將保持其適配器索引位於先前的佈局中。

換句話說,getOldPosition()返回它在移除之前位於的ViewHolder適配器位置。

所以從您的ItemDecoration#getItemOffsets方法,只是狀態裏面得到這個值:

parent.getChildViewHolder(view).getOldPosition() 

我測試它自己,它確實工作:)。