ListView是有addHeaderView和 addFooterView兩個方法的. 但是作為官方推薦的ListView的升級版RecyclerView缺無法實現這兩個方法。 那麼如果使用RecyclerView實現這兩個方法的效果該怎麼做呢? 網上查詢了很久,試過各種各樣的實現方式,終於讓我發
ListView是有addHeaderView和 addFooterView兩個方法的.
但是作為官方推薦的ListView的升級版RecyclerView缺無法實現這兩個方法。
那麼如果使用RecyclerView實現這兩個方法的效果該怎麼做呢?
網上查詢了很久,試過各種各樣的實現方式,終於讓我發現一個還不錯的實現方法,那麼就給大家推薦一下。
項目地址(別人寫的,非博主的)https://github.com/jczmdeveloper/XCRecyclerView
我看了下這個源碼,很簡單,即寫了一個繼承RecyclerView的控制項,自己實現addHeaderView和
addFooterView兩個方法
package com.xqx.com.recyclerviewheaderdemo; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; public class XCRecyclerView extends RecyclerView{ private ArrayList<View> mHeaderViews = new ArrayList<>(); private ArrayList<View> mFooterViews = new ArrayList<>(); private RecyclerView.Adapter mAdapter; private RecyclerView.Adapter mWrapAdapter; private static final int TYPE_HEADER = -101; private static final int TYPE_FOOTER = -102; private static final int TYPE_LIST_ITEM = - 103; public XCRecyclerView(Context context) { this(context, null); } public XCRecyclerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public XCRecyclerView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } private void init(Context context){ } @Override public void setAdapter(Adapter adapter) { mAdapter = adapter; mWrapAdapter = new WrapAdapter(mHeaderViews, mFooterViews, adapter); super.setAdapter(mWrapAdapter); mAdapter.registerAdapterDataObserver(mDataObserver); } public void addHeaderView(View view){ mHeaderViews.clear(); mHeaderViews.add(view); } public void addFooterView(View view){ mFooterViews.clear(); mFooterViews.add(view); } public int getHeaderViewsCount(){ return mHeaderViews.size(); } public int getFooterViewsCount(){ return mFooterViews.size(); } private final RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() { @Override public void onChanged() { mWrapAdapter.notifyDataSetChanged(); } @Override public void onItemRangeChanged(int positionStart, int itemCount) { mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount); } // @Override // public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { // mWrapAdapter.notifyItemRangeChanged(positionStart, itemCount, payload); // } @Override public void onItemRangeInserted(int positionStart, int itemCount) { mWrapAdapter.notifyItemRangeInserted(positionStart, itemCount); } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { mWrapAdapter.notifyItemMoved(fromPosition, toPosition); } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { mWrapAdapter.notifyItemRangeRemoved(positionStart, itemCount); } }; private class WrapAdapter extends RecyclerView.Adapter<ViewHolder>{ private Adapter mAdapter; private List<View> mHeaderViews; private List<View> mFooterViews; public WrapAdapter(List<View> headerViews,List<View> footerViews,Adapter adapter){ this.mAdapter = adapter; this.mHeaderViews = headerViews; this.mFooterViews = footerViews; } public int getHeaderCount(){ return this.mHeaderViews.size(); } public int getFooterCount(){ return this.mFooterViews.size(); } public boolean isHeader(int position){ return position >= 0 && position < this.mHeaderViews.size(); } public boolean isFooter(int position){ return position < getItemCount() && position >= getItemCount() - this.mFooterViews.size(); } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if(viewType == TYPE_HEADER){ return new CustomViewHolder(this.mHeaderViews.get(0)); }else if(viewType == TYPE_FOOTER){ return new CustomViewHolder(this.mFooterViews.get(0)); }else{ return this.mAdapter.onCreateViewHolder(parent,viewType); } } @Override public void onBindViewHolder(ViewHolder holder, int position) { if(isHeader(position)) return; if(isFooter(position)) return; int rePosition = position - getHeaderCount(); int itemCount = this.mAdapter.getItemCount(); if(this.mAdapter != null){ if(rePosition < itemCount){ Log.v("czm","rePosition/itemCount="+rePosition+"/"+itemCount); this.mAdapter.onBindViewHolder(holder,rePosition); return; } } } @Override public long getItemId(int position) { if (this.mAdapter != null && position >= getHeaderCount()) { int rePosition = position - getHeaderCount(); int itemCount = this.mAdapter.getItemCount(); if (rePosition < itemCount) { return this.mAdapter.getItemId(rePosition); } } return -1; } @Override public int getItemViewType(int position) { if(isHeader(position)){ return TYPE_HEADER; } if(isFooter(position)){ return TYPE_FOOTER; } int rePosition = position - getHeaderCount(); int itemCount = this.mAdapter.getItemCount(); if(rePosition < itemCount){ return this.mAdapter.getItemViewType(position); } return TYPE_LIST_ITEM; } @Override public int getItemCount() { if(this.mAdapter != null){ return getHeaderCount() + getFooterCount() + this.mAdapter.getItemCount(); }else{ return getHeaderCount() + getFooterCount(); } } @Override public void registerAdapterDataObserver(AdapterDataObserver observer) { if(this.mAdapter != null){ this.mAdapter.registerAdapterDataObserver(observer); } } @Override public void unregisterAdapterDataObserver(AdapterDataObserver observer) { if(this.mAdapter != null){ this.mAdapter.unregisterAdapterDataObserver(observer); } } private class CustomViewHolder extends ViewHolder{ public CustomViewHolder(View itemView) { super(itemView); } } } }XCRecyclerView
使用方法github里也寫的清清楚楚的
private MyAdapter mAdapter; private XCRecyclerView mRecyclerView; private List<String> mData; private View mHeaderView; private View mFooterView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mData = new ArrayList<String>(); for(int i = 0; i < 10 ;i++){ mData.add("item_" + i); } mAdapter = new MyAdapter(mData); mRecyclerView = (XCRecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); mHeaderView = LayoutInflater.from(this).inflate(R.layout.layout_header,mRecyclerView,false); mFooterView = LayoutInflater.from(this).inflate(R.layout.layout_footer,mRecyclerView,false); mRecyclerView.addHeaderView(mHeaderView); mRecyclerView.addFooterView(mFooterView); mRecyclerView.setAdapter(mAdapter); }
註意點:
addHeaderView之後 列表的數據坐標即相應發生變化!即addHeadView一次,列表第一個數據的下坐標+1(0-->1)