我们都知道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 extends RecyclerView.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