日常的开发中,我们需要为RecyclerView添加头尾布局,当我们已经写好了一个adapter,这时候如果要现在添加头尾布局,通常的做法是重写刚写完的adapter,再getItemViewType方法里返回不同的类型,并且其他方法也要改写,这样的话要改的地方太多,所以,我们可以用一个装饰类思路去设计新的adapter,在不改写原来的adapter的情况下,继续为RecyclerView添加头尾布局。在此,引出了类HeaderAndFooterWrapper.

好处:再原来的adapter上加以装饰,姿势更优雅,更解耦。

public class HeaderAndFooterWrapper<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{private static final int BASE_ITEM_TYPE_HEADER = 100000;private static final int BASE_ITEM_TYPE_FOOTER = 200000;/*** SparseArrayCompat(安卓封装自己高效的api)* 代替HashMap,只不过他们的键(key)的类型是整型Integer或者Long类型** SparseArray<T>与SparseArrayCompat<T>和LongSparseArray<T>* 这3个类中,前2个基本上是同一类,只不过第二个类有removeAt方法,第三个是Long类型的。** 如果用到了: HashMap<Integer, E> hashMap = new HashMap<Integer, E>();* 可以替换为:SparseArray<E> sparseArray = new SparseArray<E>();*///HashMap<Intent,View> mHeaderViews = new HashMap<>();private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();//头布局的viewprivate SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();//尾布局的viewprivate RecyclerView.Adapter mInnerAdapter;public HeaderAndFooterWrapper(RecyclerView.Adapter adapter){mInnerAdapter = adapter;}/*** 根据不同的头尾部返回不同的ViewHolder* 依次接收来自getItemViewType() 传过来的类型,此方法也会执行多次* 可见的view的类型都依次传进去* viewType*/@Overridepublic RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){Log.e("viewType", "viewType:== "+viewType );//View view = mHeaderViews.get(viewType);if (mHeaderViews.get(viewType) != null){View itemView = mHeaderViews.get(viewType);ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), itemView);return holder;} else if (mFootViews.get(viewType) != null){ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get(viewType));return holder;}return mInnerAdapter.onCreateViewHolder(parent, viewType);}@Overridepublic void onBindViewHolder(RecyclerView.ViewHolder holder, int position){if (isHeaderViewPos(position)){return;}if (isFooterViewPos(position)){return;}mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount());}/*** getItemViewType 返回值 是你某一种样式 的类型 是什么。。返回值也是  int类型 ,意思是  代表 A类型的 是 数字 1.。。就是这意思** 根据有无头尾部返回不同的int值** position:每一个可见的view的位置(该方法会走多次)* 该方法的作用:每个view的类型(把这个view的位置给你,你给给我返回一个类型)** 该方法会走多次,一有可见的view,就会依次把它们的位置传进去,position从零开始*/@Overridepublic int getItemViewType(int position){Log.e("getItemViewType", "getItemViewType: ==" + position);if (isHeaderViewPos(position)){//这个值其实就是我们addHeaderView时的keyint i = mHeaderViews.keyAt(position);Log.e("getItemViewType", "keyAt: =="+i);//查看第几个位置的键:return mHeaderViews.keyAt(position);} else if (isFooterViewPos(position)){return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());}//始终返回零return mInnerAdapter.getItemViewType(position - getHeadersCount());}@Overridepublic int getItemCount(){return getHeadersCount() + getFootersCount() + getRealItemCount();}@Overridepublic void onAttachedToRecyclerView(RecyclerView recyclerView){WrapperUtils.onAttachedToRecyclerView(mInnerAdapter, recyclerView, new WrapperUtils.SpanSizeCallback() {@Overridepublic int getSpanSize(GridLayoutManager layoutManager, GridLayoutManager.SpanSizeLookup oldLookup, int position) {int viewType = getItemViewType(position);if (mHeaderViews.get(viewType) != null) {return layoutManager.getSpanCount();} else if (mFootViews.get(viewType) != null) {return layoutManager.getSpanCount();}if (oldLookup != null)return oldLookup.getSpanSize(position);return 1;}});}@Overridepublic void onViewAttachedToWindow(RecyclerView.ViewHolder holder){mInnerAdapter.onViewAttachedToWindow(holder);int position = holder.getLayoutPosition();if (isHeaderViewPos(position) || isFooterViewPos(position)){WrapperUtils.setFullSpan(holder);}}private boolean isHeaderViewPos(int position){/*** position 从零开始* getHeadersCount() 头布局的总数** 这个位置小于头布局的总数就是头布局*/return position < getHeadersCount();}private boolean isFooterViewPos(int position){return position >= getHeadersCount() + getRealItemCount();}//头布局的集合public void addHeaderView(View view){mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);Log.e("mHeaderViews", "mHeaderViews.size(): =="+mHeaderViews.size());}public void addFootView(View view){mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);}//头布局view的个数public int getHeadersCount(){return mHeaderViews.size();}//尾布局的个数public int getFootersCount(){return mFootViews.size();}//Adapter 子view的个数 不包含头部的个数private int getRealItemCount(){return mInnerAdapter.getItemCount();}
}这些就是全部的代码,很简单,慢慢看看就明白了。over。

优雅的为RecyclerView添加头尾布局HeaderAndFooterWrapper相关推荐

  1. 【Android】让HeaderView也参与回收机制,自我感觉是优雅的为 RecyclerView 添加 HeaderView (FooterView)的解决方案

    本文站在巨人的肩膀上 自我感觉又进了一步而成. 基于翔神的大作基础之上写的一个为RecyclerView添加HeaderView FooterView 的另一种解决方案, 翔神链接文首镇楼:http: ...

  2. Android 优雅的为RecyclerView添加HeaderView和FooterView

    1.概述 RecyclerView通过其高度的可定制性深受大家的青睐,也有非常多的使用者开始对它进行封装或者改造,从而满足越来越多的需求. 如果你对RecyclerView不陌生的话,你一定遇到过这样 ...

  3. Android RecyclerView添加Header头部

     Android RecyclerView添加Header头部 Android RecyclerView不像以前的ListView那样直接添加头部,如果要给RecyclerView增加头部,则需要 ...

  4. Android 高级UI设计笔记20:RecyclerView 的详解之RecyclerView添加Item点击事件

    1. 引言: RecyclerView侧重的是布局的灵活性,虽说可以替代ListView但是连基本的点击事件都没有,这篇文章就来详细讲解如何为RecyclerView的item添加点击事件,顺便复习一 ...

  5. RecyclerView添加header与footer

    前言 这次主要关于RecyclerView添加header和footer的实现方法,我们都知道,在使用ListView的时候我们能自由的给自己的ListView添加头部与尾部.使用addHeaderV ...

  6. android开发 RecyclerView 瀑布列表布局

    android开发 RecyclerView 瀑布列表布局 1.写一个内容的自定义小布局: <?xml version="1.0" encoding="utf-8& ...

  7. android recyclerview添加头部,Android RecyclerView添加Header头部

     Android RecyclerView添加Header头部 Android RecyclerView不像以前的ListView那样直接添加头部,如果要给RecyclerView增加头部,则需要 ...

  8. Android框架之路——Banner实现轮播图(RecyclerView添加Header)

    一.简介 Banner能实现循环播放多个广告图片和手动滑动循环等功能.因为原生ViewPager并不支持循环翻页, 要实现循环还得需要自己去动手.Banner框架可以进行不同样式.不同动画设置, 以及 ...

  9. Android 给RecyclerView添加头部和尾部

    之前我在GitHub上开源了一个可以实现RecyclerView列表分组的通用Adapter: GroupedRecyclerViewAdapter.也在博客上写了一篇专门介绍它的实现和使用的文章:& ...

最新文章

  1. HDU - 5030 Rabbit's String(后缀数组+二分)
  2. Hbase总结(八)Hbase中的Coprocessor
  3. ActiveMQ (二) 常用配置简介
  4. 清华网红自行车火了!背后是登在《自然》上的黑科技
  5. 如何用好埋点中的数据
  6. ie工业工程,VIOOVI工时分析软件:教你一个测量工时的快捷方法
  7. micropython透明屏:esp32驱动透明屏幕通过aida64显示硬件信息
  8. ue4是什么意思_u3d和ue4的区别是什么
  9. 使用jstack排查java应用占用内存过高问题
  10. mapbox-gl加载three.js泛光效果(视频)
  11. 小程序图表wx-chart
  12. OA系统流程效率改进方案
  13. goland编译时提示\go-build\exe\a.out.exe: The process cannot access the file because it is being used
  14. RGBA和ARGB有区别吗
  15. WiFI 扫描时选择固定频率(只扫2.4G或者5G的AP)
  16. 计算机组成原理硬布线实验心得,计算机组成原理课程设计—硬布线控制器的设计与实现...
  17. ubuntu中Vim美化
  18. 基于JSP的火车高铁购票的系统【数据库设计、源码、开题报告】
  19. 全球首个5G SA部署指南发布;苹果计划用iPhone替代身份证和护照
  20. Python制作一个简易连点器

热门文章

  1. 不能一帆风顺,那就乘风破浪
  2. Go -- mac 配置Go环境
  3. 雅思词汇list1-list12总结
  4. 面试官:同事欠你500,你怎么要回来?硕士答不上,学渣智答录用
  5. keil5工具的相关配置
  6. 行为型设计模式应用(一)
  7. JQuery 基础笔记
  8. 怎么实现EDIUS 8中图片的旋转
  9. Linux也支持远程桌面,看来是孤陋寡闻了。
  10. 图书查询系统的工作原理