package com.mcxtzhang.commonadapter.rv; import android.support.v4.util.SparseArrayCompat; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; /** * 介绍:一个给RecyclerView添加HeaderView FooterView的装饰Adapter类 * 重点哦~ RecyclerView的HeaderView将可以被系统回收,不像老版的HeaderView是一个强引用在内存里 * 作者:zhangxutong * 邮箱:zhangxutong@imcoming.com * 时间: 2016/8/2. */ public abstract class HeaderRecyclerAndFooterWrapperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { protected class HeaderData { private final int DEFAULT_HEADER_VIEW_CACHE_SIZE = 5;//默认是5 和RecyclerViewPool的默认值一样 private int layoutId;//viewType当做layoutId private Object data;//该viewType(LayoutId)对应的数据 private int cacheSize;//该种viewType的HeaderView 在RecyclerViewPool的缓存池内的缓存数量 public HeaderData(int layoutId, Object data, int cacheSize) { this.layoutId = layoutId; this.data = data; this.cacheSize = cacheSize; } public HeaderData(int layoutId, Object data) { this.layoutId = layoutId; this.data = data; this.cacheSize = DEFAULT_HEADER_VIEW_CACHE_SIZE; } public int getLayoutId() { return layoutId; } public void setLayoutId(int layoutId) { this.layoutId = layoutId; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } public int getCacheSize() { return cacheSize; } public void setCacheSize(int cacheSize) { this.cacheSize = cacheSize; } } protected static final int BASE_ITEM_TYPE_FOOTER = 2000000;//footerView的ViewType基准值 //存放HeaderViews的layoudID和data,key是viewType,value 是 layoudID和data,在createViewHOlder里根据layoutId创建UI,在onbindViewHOlder里依据这个data渲染UI protected ArrayList<HeaderData> mHeaderDatas = new ArrayList<HeaderData>(); protected SparseArrayCompat<View> mFooterViews = new SparseArrayCompat<>();//存放FooterViews,key是viewType protected RecyclerView.Adapter mInnerAdapter;//内部的的普通Adapter public HeaderRecyclerAndFooterWrapperAdapter(RecyclerView.Adapter mInnerAdapter) { this.mInnerAdapter = mInnerAdapter; } public int getHeaderViewCount() { return mHeaderDatas.size(); } public int getFooterViewCount() { return mFooterViews.size(); } protected int getInnerItemCount() { return mInnerAdapter != null ? mInnerAdapter.getItemCount() : 0; } /** * 传入position 判断是否是headerview * * @param position * @return */ public boolean isHeaderViewPos(int position) {// 举例, 2 个头,pos 0 1,true, 2+ false return getHeaderViewCount() > position; } /** * 传入postion判断是否是footerview * * @param position * @return */ public boolean isFooterViewPos(int position) {//举例, 2个头,2个inner,pos 0 1 2 3 ,false,4+true return position >= getHeaderViewCount() + getInnerItemCount(); } /** * 添加HeaderView * * @param layoutId headerView 的LayoutId * @param data headerView 的data(可能多种不同类型的header 只能用Object了) */ public void addHeaderView(int layoutId, Object data) { //mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, v); /* SparseArrayCompat headerContainer = new SparseArrayCompat(); headerContainer.put(layoutId, data); mHeaderDatas.put(mHeaderDatas.size() + BASE_ITEM_TYPE_HEADER, headerContainer);*/ mHeaderDatas.add(new HeaderData(layoutId, data)); } /** * 添加HeaderView * * @param layoutId headerView 的LayoutId * @param data headerView 的data(可能多种不同类型的header 只能用Object了) * @param cacheSize 该种headerView在缓存池中的缓存个数 */ public void addHeaderView(int layoutId, Object data, int cacheSize) { //mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, v); /* SparseArrayCompat headerContainer = new SparseArrayCompat(); headerContainer.put(layoutId, data); mHeaderDatas.put(mHeaderDatas.size() + BASE_ITEM_TYPE_HEADER, headerContainer);*/ mHeaderDatas.add(new HeaderData(layoutId, data, cacheSize)); } /** * 设置某个位置的HeaderView * * @param headerPos 从0开始,如果pos过大 就是addHeaderview * @param layoutId * @param data */ public void setHeaderView(int headerPos, int layoutId, Object data) { if (mHeaderDatas.size() > headerPos) { /* SparseArrayCompat headerContainer = new SparseArrayCompat(); headerContainer.put(layoutId, data); mHeaderDatas.setValueAt(headerPos, headerContainer);*/ mHeaderDatas.get(headerPos).setLayoutId(layoutId); mHeaderDatas.get(headerPos).setData(data); } else if (mHeaderDatas.size() == headerPos) {//调用addHeaderView addHeaderView(layoutId, data); } else { // addHeaderView(layoutId, data); } } /** * 设置某个位置的HeaderView * * @param headerPos 从0开始,如果pos过大 就是addHeaderview * @param layoutId * @param data * @param cacheSize 该种headerView在缓存池中的缓存个数 */ public void setHeaderView(int headerPos, int layoutId, Object data, int cacheSize) { if (mHeaderDatas.size() > headerPos) { /* SparseArrayCompat headerContainer = new SparseArrayCompat(); headerContainer.put(layoutId, data); mHeaderDatas.setValueAt(headerPos, headerContainer);*/ mHeaderDatas.get(headerPos).setLayoutId(layoutId); mHeaderDatas.get(headerPos).setData(data); mHeaderDatas.get(headerPos).setCacheSize(cacheSize); } else if (mHeaderDatas.size() == headerPos) {//调用addHeaderView addHeaderView(layoutId, data, cacheSize); } else { // addHeaderView(layoutId, data, cacheSize); } } /** * 添加FooterView * * @param v */ public void addFooterView(View v) { mFooterViews.put(mFooterViews.size() + BASE_ITEM_TYPE_FOOTER, v); } /** * 清空HeaderView数据 */ public void clearHeaderView() { mHeaderDatas.clear(); } public void clearFooterView() { mFooterViews.clear(); } public void setFooterView(View v) { clearFooterView(); addFooterView(v); } @Override public int getItemViewType(int position) { if (isHeaderViewPos(position)) { return mHeaderDatas.get(position).getLayoutId(); } else if (isFooterViewPos(position)) {//举例:header 2, innter 2, 0123都不是,4才是,4-2-2 = 0,ok。 return mFooterViews.keyAt(position - getHeaderViewCount() - getInnerItemCount()); } return mInnerAdapter.getItemViewType(position - getHeaderViewCount()); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mHeaderDatas != null && !mHeaderDatas.isEmpty()) {//不为空,说明有headerview for (HeaderData headerData : mHeaderDatas) { if (headerData.getLayoutId() == viewType) {//匹配上了说明是headerView return ViewHolder.get(parent.getContext(), parent, viewType); } } } if (mFooterViews.get(viewType) != null) {//不为空,说明是footerview return new ViewHolder(mFooterViews.get(viewType)); } return mInnerAdapter.onCreateViewHolder(parent, viewType); } //protected abstract RecyclerView.ViewHolder createHeader(ViewGroup parent, int headerPos); protected abstract void onBindHeaderHolder(ViewHolder holder, int headerPos, int layoutId, Object o);//多回传一个layoutId出去,用于判断是第几个headerview @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (isHeaderViewPos(position)) { onBindHeaderHolder((ViewHolder) holder, position, mHeaderDatas.get(position).getLayoutId(), mHeaderDatas.get(position).getData()); return; } else if (isFooterViewPos(position)) { return; } //举例子,2个header,0 1是头,2是开始,2-2 = 0 mInnerAdapter.onBindViewHolder(holder, position - getHeaderViewCount()); } @Override public int getItemCount() { return getInnerItemCount() + getHeaderViewCount() + getFooterViewCount(); } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { mInnerAdapter.onAttachedToRecyclerView(recyclerView); //设置HeaderView的ViewHolder的缓存数量 if (null != mHeaderDatas && !mHeaderDatas.isEmpty()) { for (HeaderData headerData : mHeaderDatas) { recyclerView.getRecycledViewPool().setMaxRecycledViews(headerData.getLayoutId(), headerData.getCacheSize()); } } //为了兼容GridLayout RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; final GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup(); gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int viewType = getItemViewType(position); if (isHeaderViewPos(position)) { return gridLayoutManager.getSpanCount(); } else if (mFooterViews.get(viewType) != null) { return gridLayoutManager.getSpanCount(); } if (spanSizeLookup != null) return spanSizeLookup.getSpanSize(position); return 1; } }); gridLayoutManager.setSpanCount(gridLayoutManager.getSpanCount()); } } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { mInnerAdapter.onViewAttachedToWindow(holder); int position = holder.getLayoutPosition(); if (isHeaderViewPos(position) || isFooterViewPos(position)) { ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(true); } } } }