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也算一个列表项。