实现带header和footer功能的RecyclerView——完善篇
在上一篇文章中我們實現了實現帶header和footer功能的RecyclerView,見 ?實現帶header和footer功能的RecyclerView
但是由于加入了header,item的position有了變化,導致了RecyclerView中的一些與position有關方法或使用出現問題。本章著重解決一些常用的方法和使用,至于其他的解決方法類似。
首先,重寫幾個比較常用的方法,如下:
@Overridepublic int getChildAdapterPosition(View child) {return super.getChildAdapterPosition(child) - mWrapAdapter.getHeaderCount();}@Overridepublic void swapAdapter(Adapter adapter, boolean removeAndRecycleExistingViews) {mWrapAdapter.setAdapter(adapter);super.swapAdapter(mWrapAdapter, removeAndRecycleExistingViews);}@Overridepublic ViewHolder findViewHolderForAdapterPosition(int position) {return super.findViewHolderForAdapterPosition(position + mWrapAdapter.getHeaderCount());}
總之涉及到item的position的方法和使用都要格外注意,在需要的時候對position進行相應處理。
比如getChildAdapterPosition,我們想知道item的position。但是由于RecyclerView中實際上使用的是WrapAdapter,所以獲取的position是包括header的,所以要減去header的數量。
同理,在findViewHolderForAdapterPostion中,我們想通過外部adapter中item的postion獲取該item的ViewHolder。實際上我們是要在WrapAdapter中去取,這時考慮到header需要為這個position加上header的數量才能取到正確的ViewHolder。
上面都是比較簡單的,復雜一點比如divider。
在列表中我們經常會用到divider,RecyclerView并不像ListView那樣可以很簡單的添加divider,需要用戶自定義一個ItemDecoration。
當我們定義ItemDecoration時就需要注意與position相關的計算,因為一般情況下divider只是給正常的item來使用,header和footer不需要使用(在其布局中已經包含了)。
由于我們一般用比較簡單divider就可以了,所以這里實現了一個很簡單的默認divider,如果需要自定義參考即可,代碼如下:
public void setTransparentDivider(final int sizePx){addItemDecoration(new ItemDecoration() {@Overridepublic void onDraw(Canvas c, RecyclerView parent, State state) {super.onDraw(c, parent, state);}@Overridepublic void onDrawOver(Canvas c, RecyclerView parent, State state) {super.onDrawOver(c, parent, state);}@Overridepublic void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {int position = ((LayoutParams) view.getLayoutParams()).getViewLayoutPosition();if(mWrapAdapter.isHeader(position) || mWrapAdapter.isFooter(position)){super.getItemOffsets(outRect, view, parent, state);return;}int index = position - mWrapAdapter.getHeaderCount();if(isEnd(parent, index)){if(isVertical(parent)){outRect.set(0, 0, 0, sizePx);}else{outRect.set(0, 0, sizePx, 0);}}else{outRect.set(0, 0, sizePx, sizePx);}}private boolean isVertical(RecyclerView parent){LayoutManager layout = parent.getLayoutManager();if(layout instanceof StaggeredGridLayoutManager){return ((StaggeredGridLayoutManager) layout).getOrientation() == StaggeredGridLayoutManager.VERTICAL;}else if(layout instanceof LinearLayoutManager){return ((LinearLayoutManager) layout).getOrientation() == LinearLayoutManager.VERTICAL;}return true;}private int getSpanCount(RecyclerView parent){LayoutManager layout = parent.getLayoutManager();if(layout instanceof GridLayoutManager){return ((GridLayoutManager) layout).getSpanCount();}if(layout instanceof StaggeredGridLayoutManager){return ((StaggeredGridLayoutManager) layout).getSpanCount();}return 1;}private boolean isEnd(RecyclerView parent, int index){int spanCount = getSpanCount(parent);return (index + 1) % spanCount == 0;}});}
關于ItemDecoration的實現網上有太多的文章了,這里就不細說了。主要說說position相關需要注意的地方。
重點關注getItemOffsets這個方法,通過getViewLayoutPosistion獲取的position是item在WrapAdapter中的position。
首先判斷是否是header或footer,如果是不添加。
普通的item,由于需要判斷是否是一行的最后一個(isEnd,在GridLayoutManager或StaggeredGridLayoutManager中),所以要排除掉header對item位置的影響,這里減去header的數量。
通過上面的處理,header和footer的功能基本完善了,如果遇到其他問題,可以參照上面兩種情況進行處理。
這樣關于WrapRecyclerView的功能就告一段落了,有關onClickListener的功能很簡單,大家看一下源碼就明白了。至于更多的功能,我們以后再慢慢補充。
下一章我們會在WrapRecyclerView的基礎上實現PullToRefresh,即下拉刷新和上拉加載,敬請期待!
?源碼
完整源碼請關注公眾號:BennuCTech,發送“WrapRecyclerView”獲取。
總結
以上是生活随笔為你收集整理的实现带header和footer功能的RecyclerView——完善篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现带header和footer功能的R
- 下一篇: 为RecyclerView添加下拉刷新(