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); } } } }
使用方法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)
adapter.notifyItemChanged();等方法的坐标类似,都要相应的变化。
比如你addHeadView()一次
那么你想更新列表第4个列表项的视图,则adapter.notifyItemChanged(3+1); 多加1 headView也算一个列表项。