優雅的給RecyclerView增加多個headerView
我們都知道 Listview 可以呼叫addHeaderView 或addFootView 來新增頭尾資訊,輕鬆實現如蘇寧易購首頁,淘寶首頁那種有多個HeaderView的列表形式。 RecyclerView 現在在專案中基本都替代 ListView 和 GridView 了,然而我們新的 RecyclerView 卻沒有自帶這個功能。那只有自己去擼一個了。
實現思路
- 在Adapter裡面新建兩個列表mHeaderViews及mFooterViews把加入的Header及Footer儲存起來*
- 把Header及Footer當作正常item
- 複寫 getItemViewType 方法,通過position返回不同型別:0為原本的內容,大於0為Header, 小於0為Footer
- 複寫 onCreateViewHolder 方法。當position為0 ~ header.size-1時返回mHeaderViews的物件,header.size~header.size+count-1時為原有內容,另外就是footer了
複寫adapter問題
通過複寫adapter功能可以實現,但此庫沒有通用性,每次我們都得重新寫一下增加header的相關邏輯,通過裝飾器對adapter進行包裝達到通用的效果
實現程式碼
HeaderRecyclerView.java
package com.yy.recycleview; import android.content.Context; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; import java.util.ArrayList; public class HeaderRecyclerView extends RecyclerView { //頭view的集合 private ArrayList<HeaderViewHolder> mHeaderViewInfos=new ArrayList<>(); //腳view的集合 private ArrayList<HeaderViewHolder> mFooterViewInfos=new ArrayList<>(); private Adapter mAdapter; public HeaderRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public void addHeaderView(View v) { mHeaderViewInfos.add(new HeaderViewHolder(v)); // 如果介面卡未初始 if (mAdapter != null) { if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) { mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); } } } public void addFooterView(View v) { mFooterViewInfos.add(new HeaderViewHolder(v)); // 如果介面卡未初始 if (mAdapter != null) { if (!(mAdapter instanceof HeaderViewRecyclerAdapter)) { mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter); } } } @Override public void setAdapter(Adapter adapter) { if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { mAdapter = new HeaderViewRecyclerAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); } else { mAdapter = adapter; } super.setAdapter(mAdapter); } }
HeaderViewHolder.java
package com.yy.recycleview; import android.support.v7.widget.RecyclerView; import android.view.View; public class HeaderViewHolder extendsRecyclerView.ViewHolder{ public HeaderViewHolder(View itemView) { super(itemView); } }
HeaderViewRecyclerAdapter
package com.yy.recycleview; import android.support.v7.widget.RecyclerView; import android.view.ViewGroup; import java.util.ArrayList; public class HeaderViewRecyclerAdapter extends RecyclerView.Adapter { /** *頭條目返回大於0的資料,尾顯示小於0的資料型別 */ private ArrayList<HeaderViewHolder> mHeaderViews; private ArrayList<HeaderViewHolder> mFooterViews; private RecyclerView.Adapter mAdapter; public HeaderViewRecyclerAdapter(ArrayList<HeaderViewHolder> haderViews, ArrayList<HeaderViewHolder> footerViews, RecyclerView.Adapter mAdapter) { if (haderViews == null) { mHeaderViews = new ArrayList<HeaderViewHolder>(); } else { mHeaderViews = haderViews; } if (footerViews == null) { mFooterViews = new ArrayList<HeaderViewHolder>(); } else { mFooterViews = footerViews; } this.mAdapter=mAdapter; } @Override public int getItemViewType(int position) { //header 型別為正數,通過type可以換算出position int numHeaders = getHeadersCount(); if (position < numHeaders) { return position+1; } // Adapter 正常為0 final int realPosition = position - numHeaders; int realAdapterCount = 0; if (mAdapter != null) { realAdapterCount = mAdapter.getItemCount(); if (realPosition < realAdapterCount) { return mAdapter.getItemViewType(realPosition); } } // Footer 用負數表示型別 return-(position-numHeaders-realAdapterCount)-1; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { int index; if(viewType==0)return mAdapter.onCreateViewHolder(parent,viewType); else if(viewType>0){ index=viewType-1; return mHeaderViews.get(index); } else{ index=index=-viewType-1; return mFooterViews.get(index); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //也要劃分三個區域 int numHeaders = getHeadersCount(); if (position < numHeaders) {//是頭部 return; } //原來的adapter正常內容 final int realPosition = position - numHeaders; int adapterCount = 0; if (mAdapter != null) { adapterCount = mAdapter.getItemCount(); if (realPosition < adapterCount) { mAdapter.onBindViewHolder(holder, realPosition); return; } } //尾部 } @Override public int getItemCount() { if (mAdapter != null) { return getFootersCount() + getHeadersCount() + mAdapter.getItemCount(); } else { return getFootersCount() + getHeadersCount(); } } /** * * @return Header的個數 */ public int getHeadersCount() { return mHeaderViews.size(); } /** * footer的個數 * @return */ public int getFootersCount() { return mFooterViews.size(); } }
Demo請移步https://github.com/kx1115/HeaderAndFooterRecycleViewDemo