recyclerView通用适配器,支持添加多个header和footer
每个RecyclerView都要写一个适配器很浪费时间。
- 设置header和footer就是RecyclerView设置不同type的Item。
- onCreatedViewHolder()绑定不同布局(item),抽象出一个方法getItemLayoutId()。
- 绑定数据onBindViewHolder中设置了一个onBind()方法。
- 给item设置点击事件,已经把header和footer的item的点击事件屏蔽了
以下是全部代码:
package com.lanjiejie.adapter;
import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
/**
* recyclerView 适配器
*/
public abstract class BaseRecycleViewAdapter<T> extends RecyclerView.Adapter<BaseRecyclerViewHolder> {
public static final int TYPE_NORMAL = 1;
private static final int TYPE_FLAG = 100000;
private Context mContext;
private List<T> mDataList;
private LayoutInflater mLayoutInflater;
private List<View> mHeaderViews = new ArrayList<>();
private List<View> mFooterViews = new ArrayList<>();
private List<Integer> mHeaderViewTypes = new ArrayList<>();
private List<Integer> mFooterViewTypes = new ArrayList<>();
private OnItemClickListener mClickListener;
public BaseRecycleViewAdapter(Context context, List<T> dataList) {
this.mContext = context;
this.mDataList = dataList;
mLayoutInflater = LayoutInflater.from(mContext);
}
@Override
public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mHeaderViewTypes.contains(viewType)) {
return new BaseRecyclerViewHolder(mContext, mHeaderViews.get(viewType / TYPE_FLAG));
}
if (mFooterViewTypes.contains(viewType)) {
int index = viewType / TYPE_FLAG - mDataList.size() - mHeaderViews.size();
return new BaseRecyclerViewHolder(mContext, mFooterViews.get(index));
}
return new BaseRecyclerViewHolder(mContext, mLayoutInflater.inflate(getItemLayoutId(viewType), parent, false));
}
@Override
public void onBindViewHolder(final BaseRecyclerViewHolder holder, final int position) {
if (isFooter(position) || isHeader(position))
return;
final int realPos = getRealPosition(position);
if (realPos < mDataList.size()) {
final T data = mDataList.get(realPos);
onBind(holder, realPos, data);
}
if (mClickListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mClickListener.onItemClick(holder.itemView, realPos);
}
});
}
}
@Override
public int getItemCount() {
return mDataList.size() + mHeaderViews.size() + mFooterViews.size();
}
@Override
public int getItemViewType(int position) {
if (mHeaderViews.size() > 0 && position < mHeaderViews.size()) {
//用position作为HeaderView 的 ViewType标记
//记录每个ViewType标记
mHeaderViewTypes.add(position * TYPE_FLAG);
return position * TYPE_FLAG;
}
if (mFooterViews.size() > 0 && mFooterViews.size() > 0 && position >= getItemCount() - mFooterViews.size()) {
//用position作为FooterView 的 ViewType标记
//记录每个ViewType标记
mFooterViewTypes.add(position * TYPE_FLAG);
return position * TYPE_FLAG;
}
return TYPE_NORMAL;
}
public int getRealPosition(int position) {
return position - mHeaderViews.size();
}
/**
* 必须在setAdapter之前添加
*
* @param view header
*/
public void addHeaderView(View view) {
mHeaderViews.add(view);
}
/**
* 必须在setAdapter之前添加
*
* @param view footer
*/
public void addFooterView(View view) {
mFooterViews.add(view);
}
private boolean isHeader(int position) {
return mHeaderViews.size() > 0 && position < mHeaderViews.size();
}
private boolean isFooter(int position) {
return mFooterViews.size() > 0 && position >= getItemCount() - mFooterViews.size();
}
/**
* 当LayoutManager是GridLayoutManager时,设置header和footer占据的列数
* @param recyclerView recyclerView
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) layoutManager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (isFooter(position) || isHeader(position))
? gridManager.getSpanCount() : 1;
}
});
}
}
/**
* 当LayoutManager是StaggeredGridLayoutManager时,设置header和footer占据的列数
* @param holder holder
*/
@Override
public void onViewAttachedToWindow(BaseRecyclerViewHolder holder) {
super.onViewAttachedToWindow(holder);
final ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
if (layoutParams != null && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) layoutParams;
params.setFullSpan(isHeader(holder.getLayoutPosition())
|| isFooter(holder.getLayoutPosition()));
}
}
/**
* 绑定数据
* @param viewHolder holder
* @param position pos
* @param data 数据源
*/
public abstract void onBind(BaseRecyclerViewHolder viewHolder, int position, T data);
/**
* item 布局id
*
* @param viewType item type
* @return item 布局id
*/
abstract public int getItemLayoutId(int viewType);
public interface OnItemClickListener {
void onItemClick(View itemView, int pos);
void onItemLongClick(View itemView, int pos);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mClickListener = listener;
}
}
ViewHolder仿照鸿洋大神的listView的holder
public class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {
private SparseArray<View> mViews;
private Context mContext;
public BaseRecyclerViewHolder(Context context, View itemView) {
super(itemView);
this.mContext = context;
mViews = new SparseArray<>();
}
private <T extends View> T findViewById(int viewId) {
View view = mViews.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
public View getView(int viewId) {
return findViewById(viewId);
}
}
需要注意:
- 绑定数据源时的position,记得有几个header就减去几。参见:方法getRealPosition()