RecyclerView添加Header和Footer的基本原理
来源:互联网 发布:相片搭配服装软件 编辑:程序博客网 时间:2024/04/29 23:48
GitHub
- GitHub
介绍
采用的基本原理就是Header和Footer作为RecyclerView的一个Item,只是显示的方式特别一点,ListView实际也是这么做的所以添加了Header之后,数据的位置会错乱。
由于使用不同的LayoutManager时显示效果也不一样, 所以针对不同的LayoutManager需要做不同的操作。
分析一下,LinearLayoutManager比较简单,只需要将Header和Footer作为一项就可以了,GridLayoutManager和StaggeredGridLayoutManager在这个基础上还需要将Header和Footer所在的Item充满他所在的这一行。
变量和方法
//Header和Footer,以及对应的Typeprivate View mHeaderView;private View mFooterView;private int TYPE_HEADER = -1;private int TYPE_FOOTER = -2;//一些辅助的方法public int getHeaderCount() { return isHasHeader() ? 1 : 0;}private boolean isHasHeader() { return mHeaderView != null;}private boolean isHasFooter() { return mFooterView != null;}
根据是否有Header和Footer获取数据Size
//根据是否有Header和Footer返回不同的Size@Overridepublic int getItemCount() { int pos = datas.size(); if (isHasHeader()) pos++; if (isHasFooter()) pos++; return pos;}
根据是否有Header和Footer获取Type
//获取item的type,基本逻辑是如果有header又是位于第一个的则返回HeaderType,如果pos超出了data的size,又是最后一个,则返回FooterType@Overridepublic int getItemViewType(int position) { //如果没有header没有footer直接返回 if (!isHasHeader() && !isHasFooter()) return datas.get(position).getRvType(); //有header且位置0 if (isHasHeader() && position == 0) return TYPE_HEADER; //pos超出 if (isHasFooter() && position == getItemCount() - 1) return TYPE_FOOTER; //如果有header,下标减一个 if (isHasHeader()) return datas.get(position - 1).getRvType(); else //没有header 按照原来的 return datas.get(position).getRvType();}
根据是否有Header和Footer创建Holder
//根据返回的不同的type使用HeaderView和FooterView初始化Holder,至此已经可以对LinearLayoutManager添加Header和Footer@Overridepublic RvViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RvViewHolder holder; if (isHasFooter() && viewType == TYPE_FOOTER) { holder = new RvFooterHolder(mFooterView); } else if (isHasHeader() && viewType == TYPE_HEADER) { holder = new RvHeaderHolder(mHeaderView); } else { holder = new RvViewHolder(getInflateView(Res4Type.get(viewType).getResId(), return holder;}
LinearLayoutManager
- 由于LinearLayoutManager是连续排列的,所以只需要创建不同的holder就可以实现header+footer
GridLayoutManager
- 首先如何知道是否是GridLayoutManager,重写
onAttachedToRecyclerView
方法获取Manager,调用gridLayoutManager.setSpanSizeLookup()
方法,设置他跨越的宽度。
@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); Log.e("chendong","onAttachedToRecyclerView"); RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return getItemViewType(position) == TYPE_HEADER || getItemViewType(position) == TYPE_FOOTER ? gridLayoutManager.getSpanCount() : 1; } }); return; } //判断是不是StaggeredGridLayoutManager if(layoutManager instanceof StaggeredGridLayoutManager){ isStaggeredGridLayoutManager = true; }}
StaggeredGridLayoutManager
- 主要使用StaggeredGridLayoutManager.LayoutParams的 layoutParams.setFullSpan(true);方法设置
@Overridepublic RvViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RvViewHolder holder; if (isHasFooter() && viewType == TYPE_FOOTER) { holder = new RvFooterHolder(mFooterView); } else if (isHasHeader() && viewType == TYPE_HEADER) { holder = new RvHeaderHolder(mHeaderView); } else { holder = new RvViewHolder(getInflateView(Res4Type.get(viewType).getResId(), parent)); if (clickListener != null) { holder.setOnItemClickListener(clickListener); } if (longClickListenter != null) { holder.setOnItemLongClickListener(longClickListenter); } } //关键代码 if (isStaggeredGridLayoutManager && (holder instanceof RvHeaderHolder || holder instanceof RvFooterHolder)) { Log.e("chendong","瀑布流设置满行"); StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); layoutParams.setFullSpan(true); holder.getParentView().setLayoutParams(layoutParams); } bindListener4View(holder, viewType); return holder;}
QuickAdapter
- 最后贴一下整个QuickAdapter的源代码,涉及相关具体的类可以去这里查看
package com.march.quickrvlibs;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.util.SparseArray;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import com.march.quickrvlibs.inter.OnRecyclerItemClickListener;import com.march.quickrvlibs.inter.OnRecyclerItemLongClickListener;import com.march.quickrvlibs.inter.RvQuickInterface;import java.util.Collections;import java.util.List;/** * Created by 陈栋 on 15/12/28. * 功能: */public abstract class RvQuickAdapter<D extends RvQuickInterface> extends RecyclerView.Adapter<RvViewHolder> { protected List<D> datas; protected LayoutInflater mLayoutInflater; protected Context context; protected SparseArray<RvAdapterConfig> Res4Type; private OnRecyclerItemClickListener<RvViewHolder> clickListener; private OnRecyclerItemLongClickListener<RvViewHolder> longClickListenter; private View mHeaderView; private View mFooterView; private int TYPE_HEADER = -1; private int TYPE_FOOTER = -2; private int adapterId;//使用此标志来判断当前adapter的类型 private boolean isStaggeredGridLayoutManager = false; public int getAdapterId() { return adapterId; } /** * 设置adapterId标示 * @param adapterId adapter标示 */ public void setAdapterId(int adapterId) { this.adapterId = adapterId; } /** * 使用标记判断,是否是该adaper * @param adapter adapter * @return boolean */ public boolean isThisAdapter(RvQuickAdapter adapter) { if (adapter == null) { return false; } else if (adapter.getAdapterId() == adapterId) { return true; } return false; } /** * 多类型适配,需要调用addType()方法配置参数 * * @param context context * @param datas 数据源 */ public RvQuickAdapter(Context context, List<D> datas) { this.datas = datas; this.mLayoutInflater = LayoutInflater.from(context); this.context = context; } public RvQuickAdapter(Context context, D[] ds) { Collections.addAll(datas, ds); this.mLayoutInflater = LayoutInflater.from(context); this.context = context; } /** * 单类型适配 * * @param context context * @param datas 数据源 * @param res layout资源 */ public RvQuickAdapter(Context context, List<D> datas, int res) { this.datas = datas; this.mLayoutInflater = LayoutInflater.from(context); this.context = context; this.Res4Type = new SparseArray<>(); Res4Type.put(0, new RvAdapterConfig(0, res)); } public RvQuickAdapter(Context context, D[] ds, int res) { Collections.addAll(datas, ds); this.mLayoutInflater = LayoutInflater.from(context); this.context = context; this.Res4Type = new SparseArray<>(); Res4Type.put(0, new RvAdapterConfig(0, res)); } public void setClickListener(OnRecyclerItemClickListener<RvViewHolder> listener) { if (listener != null) { this.clickListener = listener; } } public void setLongClickListener(OnRecyclerItemLongClickListener<RvViewHolder> longClickListenter) { if (longClickListenter != null) { this.longClickListenter = longClickListenter; } } public void addHeader(View mHeaderView) { this.mHeaderView = mHeaderView; } public void addFooter(View mFooterView) { this.mFooterView = mFooterView; } public void addHeader(int mHeaderViewRes) { this.mHeaderView = getInflateView(mHeaderViewRes, null); } public void addFooter(int mFooterViewRes) { this.mFooterView = getInflateView(mFooterViewRes, null); } public View getInflateView(int resId, ViewGroup parent) { return mLayoutInflater.inflate(resId, parent, false); } @Override public RvViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RvViewHolder holder; if (isHasFooter() && viewType == TYPE_FOOTER) { holder = new RvFooterHolder(mFooterView); } else if (isHasHeader() && viewType == TYPE_HEADER) { holder = new RvHeaderHolder(mHeaderView); } else { holder = new RvViewHolder(getInflateView(Res4Type.get(viewType).getResId(), parent)); if (clickListener != null) { holder.setOnItemClickListener(clickListener); } if (longClickListenter != null) { holder.setOnItemLongClickListener(longClickListenter); } } if (isStaggeredGridLayoutManager && (holder instanceof RvHeaderHolder || holder instanceof RvFooterHolder)) { Log.e("chendong","瀑布流设置满行"); StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); layoutParams.setFullSpan(true); holder.getParentView().setLayoutParams(layoutParams); } bindListener4View(holder, viewType); return holder; } @Override public void onBindViewHolder(RvViewHolder holder, int position) { if (isHasFooter() && position == getItemCount() - 1) { bindLisAndData4Footer((RvFooterHolder) holder); } else if (isHasHeader() && position == 0) { bindLisAndData4Header((RvHeaderHolder) holder); } else { int pos = judgePos(position); bindData4View(holder, datas.get(pos), pos, datas.get(pos).getRvType()); } } @Override public int getItemViewType(int position) { //如果没有header没有footer直接返回 if (!isHasHeader() && !isHasFooter()) return datas.get(position).getRvType(); //有header且位置0 if (isHasHeader() && position == 0) return TYPE_HEADER; //pos超出 if (isHasFooter() && position == getItemCount() - 1) return TYPE_FOOTER; //如果有header,下标减一个 if (isHasHeader()) return datas.get(position - 1).getRvType(); else //没有header 按照原来的 return datas.get(position).getRvType(); } private int judgePos(int pos) { if (isHasHeader()) { return pos - 1; } else { return pos; } } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); Log.e("chendong","onAttachedToRecyclerView"); RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return getItemViewType(position) == TYPE_HEADER || getItemViewType(position) == TYPE_FOOTER ? gridLayoutManager.getSpanCount() : 1; } }); return; } if(layoutManager instanceof StaggeredGridLayoutManager){ isStaggeredGridLayoutManager = true; } } /** * 绑定数据 * * @param holder ViewHolder数据持有者 * @param data 数据集 * @param pos 数据集中的位置 * @param type type */ public abstract void bindData4View(RvViewHolder holder, D data, int pos, int type); /** * 绑定监听器 * * @param holder ViewHolder数据持有者 * @param type type */ public void bindListener4View(RvViewHolder holder, int type) { } /** * 绑定header的数据 和 监听 * * @param holder header holder */ public void bindLisAndData4Header(RvHeaderHolder holder) { } /** * 绑定footer的数据和监听 * * @param holder footer holder */ public void bindLisAndData4Footer(RvFooterHolder holder) { } @Override public int getItemCount() { int pos = datas.size(); if (isHasHeader()) pos++; if (isHasFooter()) pos++; return pos; } public int getHeaderCount() { return isHasHeader() ? 1 : 0; } public int getDataPos(int pos) { return pos - getHeaderCount(); } private boolean isHasHeader() { return mHeaderView != null; } private boolean isHasFooter() { return mFooterView != null; } /** * @param type 数据的类型(如果有n种类型,那么type的值需要是0 ~ n-1) * @param resId 该类型对应的资源文件的id * @return QuickTypeAdapter */ public RvQuickAdapter<D> addType(int type, int resId) { if (this.Res4Type == null) this.Res4Type = new SparseArray<>(); this.Res4Type.put(type, new RvAdapterConfig(type, resId)); return this; }}
0 0
- RecyclerView添加Header和Footer的基本原理
- RecyclerView添加Header和Footer的方法
- RecyclerView优雅的添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加Header和Footer
- RecyclerView添加header和footer
- RecyclerView添加header和footer
- RecyclerView 添加 Header 和 Footer
- RecyclerView添加Header和Footer
- RecyclerView的使用(3)之添加Header和Footer
- RecyclerView的使用(3)之添加Header和Footer
- 使用RecyclerView添加Header和Footer的方法
- 使用RecyclerView添加Header和Footer的方法
- 为RecyclerView添加header和footer
- 给RecyclerView添加header和footer
- RecyclerView:带header和footer的grid
- RecyclerView 添加 Footer and Header
- 作为一个新人,怎样学习嵌入式Linux?(韦东山)
- 一些有用的网站
- 编译原理-0-编译过程概述
- C++实验3-1-个人所得税计算器
- 作业:C++作业3
- RecyclerView添加Header和Footer的基本原理
- 冒泡排序(Bubble Sort)
- 初学java
- 安装arm-linux-gdb
- LOD优化
- 对象数组
- LayoutInflater的用法
- SQL基础语法笔记教程整理
- poj 1985 Cow Marathon