RecyclerView的使用(二):添加头部和尾部

2023-05-16

前言

Recyclerview作为Android的常用控件之一,相信大家对它应该是十分熟悉了,不熟悉的朋友可以参考我之前发的文章 RecyclerView的基本使用,其中包括有单item及多Item的基本使用。

但是我们发现Recyclerview中没有提供方法直接添加headerViewfootView。对于我们自己去使用来说还需要从getItemViewType方法中进行重写,根据不同的类型添加不同的item布局,具体实现可以参考 RecyclerView的基本使用 中多item的使用。下面讨论下如何实现类似于ListViewaddHeaderView方法来添加列表的头部和尾部。

设计与实现

既然类比于ListView中的添加头部和尾部的方法,我们首先要先理清在listView中是如何去实现的,直接上源码:

    public void addHeaderView(View v, Object data, boolean isSelectable) {
        if (v.getParent() != null && v.getParent() != this) {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "The specified child already has a parent. "
                           + "You must call removeView() on the child's parent first.");
            }
        }
        final FixedViewInfo info = new FixedViewInfo();
        info.view = v;
        info.data = data;
        info.isSelectable = isSelectable;
        mHeaderViewInfos.add(info);
        mAreAllItemsSelectable &= isSelectable;

        // Wrap the adapter if it wasn't already wrapped.
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewListAdapter)) {
                wrapHeaderListAdapterInternal();
            }

            // In the case of re-adding a header view, or adding one later on,
            // we need to notify the observer.
            if (mDataSetObserver != null) {
                mDataSetObserver.onChanged();
            }
        }
    }

从代码中可以看出,listView中对adapter进行了封装:HeaderViewListAdapter,使用此类用来处理对HeaderView的处理。
查看此类代码,能够看出设计思想是通过使用了装饰模式的思路,对原有的adapter进行重新装饰,生成装饰类HeaderViewListAdapter用来处理head view。其重点工作包括如下几项:

  1. 重新计算count。
  2. 重新计算position对应的View的不同。

了解了上述思路,接下来我们就可以动手去实现了,首先我们可以自定义一个继承自RecyclerView的控件,定义可以添加头部和尾部的方法,如下:

class TestHeaderRecyclerView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RecyclerView(context, attrs, defStyleAttr) {
    private var headerViews: ArrayList<View> = ArrayList()
    private var footerViews: ArrayList<View> = ArrayList()
    
    public fun addHeaderView(headerView: View) {
        headerViews.clear()
        headerViews.add(headerView)
    }

    public fun addFooterView(footerView: View) {
        footerViews.clear()
        footerViews.add(footerView)
    }

    public fun setAdapter(testAdapter: TestAdapter) {
        var adapter = TestHeaderAdapter(headerViews, footerViews, testAdapter)
        this.adapter = adapter
    }
}

然后实现一个adapter类去装饰原有的adapter,其实最终的实现方式也是通过设置adapter中不同的itemType去添加不同的布局View,示例代码如下:

class TestHeaderAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>, IWrapperAdapter {
    private var mAdapter: TestAdapter? = null
    private var headerViews: ArrayList<View>? = ArrayList()
    private var footerViews: ArrayList<View>? = ArrayList()
    private var currentPosition: Int = 0

    constructor(
            headViews: ArrayList<View>,
            footViews: ArrayList<View>,
            adapter: TestAdapter
    ) {
        headerViews = headViews
        footerViews = footViews
        this.mAdapter = adapter
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        when (viewType) {
            TYPE_HEADER -> {
                if (headerViews?.get(0) != null) {
                    return HeadViewHolder(headerViews!![0])
                }
            }
            TYPE_FOOTER -> {
                if (footerViews?.get(0) != null) {
                    return FootViewHolder(footerViews!![0])
                }
            }
            TYPE_INVALID -> {

            }
            else -> {
            }
        }
        return mAdapter!!.onCreateViewHolder(parent, viewType)
    }

    override fun getItemCount(): Int {
        return if (mAdapter != null)
            mAdapter!!.itemCount + getFooterCount() + getHeaderCount()
        else
            getFooterCount() + getHeaderCount()
    }

    override fun getHeaderCount(): Int {
        return headerViews?.size ?: 0
    }

    override fun getFooterCount(): Int {
        return footerViews?.size ?: 0
    }

    override fun getItemViewType(position: Int): Int {
        currentPosition = position
        if (currentPosition < getHeaderCount())
            return TYPE_HEADER
        if (mAdapter != null) {
            if (currentPosition < itemCount - getFooterCount()) {
                return mAdapter!!.getItemViewType(currentPosition - getHeaderCount())
            }
            return TYPE_FOOTER
        }
        return TYPE_INVALID

    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        var headCount = getHeaderCount()
        if (position < headCount) {
            return
        }
        var cPosition = position - headCount
        if (mAdapter != null) {
            var adapterCount = mAdapter!!.itemCount
            if (cPosition < adapterCount) {
                mAdapter!!.onBindViewHolder(holder, cPosition)
                return
            }
        }
    }

    class HeadViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    }

    class FootViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    }

    companion object {
        const val TYPE_HEADER = -1
        const val TYPE_FOOTER = -2
        const val TYPE_INVALID = -3
    }
}

这样最后调用的时候直接调用addHeaderViewaddFooterView即可添加View,如下:

    private fun setSimpleAdapter(listData: ArrayList<TestData>) {
        var headView1 = TestHeaderView(this)
        var footView1 = TestHeaderView(this)
        var testAdapter = TestAdapter(listData)
        listView?.addHeaderView(headView1)
        listView?.addFooterView(footView1)
        listView?.setAdapter(testAdapter)
        listView?.addItemDecoration(DividerItemDecoration(this,DividerItemDecoration.VERTICAL))
        listView?.layoutManager = LinearLayoutManager(this)
    }

效果如下图:

在这里插入图片描述

总结

类比于ListView的添加头尾部思路,为Recyclerview设计添加头尾部,本质上还是通过不同的itemtype实现不同的布局。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RecyclerView的使用(二):添加头部和尾部 的相关文章

  • RecyclerView 隐藏部分分割线

    在项目中遇到复杂点的RecyclerView xff0c 可能会有隐藏部分分割线的需求 xff0c 例如item1和item3之间的分割线隐藏 xff0c item4和item5之间的分割线隐藏等 在看了文档里的ItemDecoration
  • RecyclerView的使用(二):添加头部和尾部

    前言 Recyclerview作为Android的常用控件之一 xff0c 相信大家对它应该是十分熟悉了 xff0c 不熟悉的朋友可以参考我之前发的文章 RecyclerView的基本使用 xff0c 其中包括有单item及多Item的基本
  • RecyclerView 使用总结以及常见问题解决方案

    1 RecycleView设置了数据不显示 本文主要讲一下我个人对于RecycleView的使用的一些思考以及一些常见的问题怎么解决 先来看一下使用RecycleView时常见的问题以及一些需求 这个往往是因为你没有设置LayoutMang
  • 字节4轮面试,3轮都问了RecyclerView

    阿里面试总共4轮 xff0c 其中有3轮面试都问到了RecyclerView的问题 面试的点各不相同 xff0c 有原理 嵌套问题 有缓存实现 xff0c 但是最终都是殊途同归 xff0c 所有的问题都汇集在 如何对RecyclerView
  • recycler recyclerview snaphelper

    转载 xff1a 让你明明白白的使用RecyclerView SnapHelper详解 简书
  • RecyclerView 隐藏部分分割线

    在项目中遇到复杂点的RecyclerView xff0c 可能会有隐藏部分分割线的需求 xff0c 例如item1和item3之间的分割线隐藏 xff0c item4和item5之间的分割线隐藏等 在看了文档里的ItemDecoration
  • RecyclerView中倒计时item的优雅方案

    本文介绍在RecyclerView中使用倒计时楼层 xff0c 并且每秒刷新显示倒计时 没有纠结于样式 xff0c 主要介绍代码结构和设计模式 先看一下效果 xff1a 我们采取的是观察者模式的方法 xff0c 启动一个handler xf
  • RecyclerView系列 - RecyclerView的基本使用

    文章欢迎转载 转载请注明出处 文章首发于 Karen Chia 程序人生 RecyclerView系列 RecyclerView的基本使用 按照惯例 先上效果图 效果图不是我想要的效果 怎么办 查看关于 RecyclerView 系列的其它
  • RecyclerView放入正方形布局

    在使用RevyclerView时 有个需求 列表列数不固定 每个item的高度要和宽度相等具体看图 三列 四列 五列
  • Android RecyclerView对应的适配器中方法的执行顺序和具体作用详解

    前些天发现了一个蛮有意思的人工智能学习网站 8个字形容一下 通俗易懂 风趣幽默 感觉非常有意思 忍不住分享一下给大家 点击跳转到教程 1 代码的执行顺序为 首次进入会先调用getItemCount 返回条目的个数 之后会分别调用 getIt
  • RecyclerView流式布局StaggeredGridLayoutManager,重排序问题

    RecyclerView天然支持流式布局 只需要设置layoutManager为StaggeredGridLayoutManager 不过如果item中有图片 由于图片异步加载 会导致item布局变化 这倒也没什么 关键是在holder复用
  • android如果将recyclerView嵌套进NestedScrollView中,可能导致加载更多一直执行

    今天在使用BaseQuickAdapter对RecyclerView进行绑定的时候 支持加载更多 却发现一直自动进行加载更多 最后发现问题是因为在NestedScrollView中的缘故 还不知为什么
  • Android RecyclerView的notify方法和动画的刷新详解

    前些天发现了一个蛮有意思的人工智能学习网站 8个字形容一下 通俗易懂 风趣幽默 感觉非常有意思 忍不住分享一下给大家 点击跳转到教程 前言 本篇讲解了RecyclerView关于通知列表刷新的常用的notify方法 和RecyclerVie
  • Android RecyclerView实现树形列表

    前段时间公司有个项目 需要展示客户关系的树形列表 当时网上找了一些资料 有些觉得挺复杂的 有些测试下来有bug 最终决定自己解决 最底下有demo 需要源码的同学可以下载 效果图 带节点的展开与收缩 并且可以实现项的单选 选中项字体为蓝色
  • 蜗牛君漫聊动态布局框架(二):核心功能的思路与实现

    Hello 大家好 我是蜗牛君 我们又见面了 本篇文章是蜗牛君漫聊动态布局框架的第二篇 上一篇中我们讲解了框架的大致思路 以及复习了一下RecyclerView的基础使用方式 那么本篇文章我们就正式开始框架的搭建了 首先我们要做一件事情 就
  • 如何让RecyclerView滑动到底部?

    在做这个功能时 使用scroll的任何一个方法 发现它每次都只滑到了一半 今天终于解决了 解决方法如下 LinearLayoutManager linearLayoutManager LinearLayoutManager recycler
  • NestedScrollView嵌套RecyclerView只显示一行的问题

    1 添加属性设置 设置布局管理器 LinearLayoutManager linearLayoutManager new LinearLayoutManager context linearLayoutManager setOrientat
  • 蜗牛君漫聊动态布局框架(三):适配器与创建者

    大家好 欢迎来到蜗牛君漫聊动态布局框架专题 上篇文章中我们介绍完了框架的核心功能实现 本篇继续介绍剩下的所有功能 不同类型ViewHolder的动态创建已经完成 接下来我们要实现数据与布局的中间件 适配器 Adapter 代码实现 中间件
  • RecyclerView实现九宫格和点击事件

    想要实现的效果如下 开始界面 点击界面展示 在屏幕中间弹出一个对话框 效果就如同将图片放大一样 不过当然 这里的图片放大并非真正意义上的拉伸 而是展示出较大的那张图片 若是不打算用两张图片 也可以自定义大小 这里因为只是简单的demo 也为
  • Android RecyclerView的StaggeredGridLayoutManager布局,实现交错排列的子元素分组

    先看实现的效果图 设计背景 现在的产品对设计的需求越来越多样化 如附录文章2是典型的联系人分组RecyclerView 子元素排列到一个相同的组 但是有些时候 UI要求把这些元素不是垂直方向的 而是像本文开头的图中所示样式排列 这就需要用S

随机推荐

  • Ubuntu 22.04下载安装VMware Workstation Pro 17

    Ubuntu 22 04下载安装VMware Workstation Pro 17 一 下载 打开浏览器 xff0c 访问VMware的官方网站 xff1a https www vmware com 页面打开后 xff0c 点击菜单中的 A
  • CentOS开启SSH免密登录

    CentOS开启SSH免密登录 要实现SSH免密登录 xff0c 首先需要准备一组公钥和私钥 将公钥放到服务器上 xff0c 将私钥放到客户机上 当客户机连接服务器时 xff0c 服务器会根据自身的公钥校验客户机的私钥 xff0c 如果校验
  • Ubuntu开启SSH免密登录

    Ubuntu开启SSH免密登录 要实现SSH免密登录 xff0c 首先需要准备一组公钥和私钥 将公钥放到服务器上 xff0c 将私钥放到客户机上 当客户机连接服务器时 xff0c 服务器会根据自身的公钥校验客户机的私钥 xff0c 如果校验
  • CentOS Stream 9 编译安装6.1内核

    CentOS Stream 9 编译安装6 1内核 一 下载内核源码 打开浏览器 xff0c 访问Linux内核的官方网站 xff1a https www kernel org 在官网首页能够看到许多不同的内核版本 xff0c 位于右边的黄
  • Windows 11安装Visual Studio 2022

    Windows 11安装Visual Studio 2022 一 下载 打开浏览器 xff0c 访问Visual Studio的官方网站 xff1a https visualstudio microsoft com 将页面向下拉动 xff0
  • CentOS Stream 9编译安装Redis 7

    CentOS Stream 9编译安装Redis 7 一 下载 1 访问Redis官方网站 xff1a https redis io xff0c 点击菜单栏右侧的 Download 进入下载页面 2 在下载页面的左侧可以看到Redis相关信
  • Flash定时器

    基于计时器的动画 作为计时器动画使用的关键类 xff0c 不出意料 xff0c 它就是 flash utils Timer 同时我们还需要 flash events TimerEvent 类 使用计时器实际上与使用 enterFrame 没
  • win10系统隐藏u盘EFI分区的方法(附图)

    windows10系统升级最新1703版本后发现制作pe系统的u盘插上电脑后会同时显示可见分区和efi分区 xff0c 以前的efi隐藏手段统统失效了 xff0c 目前没找到完美的方法 xff0c 本文的方法是在自己电脑隐藏efi分区 xf
  • 数据库加密错误file is not a database

    问题描述 日前在调研数据库加密是在书写demo时发现了一个错误 xff1a file is not a database while compiling select count from sqlite master 问题分析 从日志上来看
  • 面试题:从给定的N个正数中选取若干个数之和最接近M

    这道题跟捞鱼问题一样 xff0c 都是刚进实验室新生培训那会儿做过的题目 xff0c 不过这个是一师姐当时找工作的面试题 如题 xff0c 并输出该子序列 测试用例 xff1a 2 xff0c 9 xff0c 5 xff0c 7 xff0c
  • 贝叶斯最优分类器

    贝叶斯常常有两个问题 xff1a xff08 1 xff09 给定训练数据 xff0c 最可能的假设是什么 xff1f xff08 2 xff09 给定训练数据 xff0c 对新实例的最可能分类是什么 xff1f 第一个问题用最大后验概率
  • 奇异值分解SVD应用—LSI/LSA

    原文 xff1a http blog csdn net abcjennifer article details 8131087 xff08 有看不懂的地方 xff0c 原文评论有点解答 xff09 潜在语义索引 xff08 Latent S
  • EAGAIN、EWOULDBLOCK、EINTR与非阻塞 长连接

    EAGAIN EWOULDBLOCK EINTR与非阻塞 长连接 EWOULDBLOCK用于非阻塞模式 xff0c 不需要重新读或者写 EINTR指操作被中断唤醒 xff0c 需要重新读 写 在Linux环境下开发经常会碰到很多错误 设置e
  • WebSocket 实战

    本文介绍了 HTML5 WebSocket 的由来 xff0c 运作机制及客户端和服务端的 API 实现 xff0c 重点介绍服务端 xff08 基于 Tomcat7 xff09 及客户端 xff08 基于浏览器原生 HTML5 API x
  • makefile 编写之32 or 64位机器

    一 Makefile 判断 64位机器 ARCH 61 shell uname m BIT32 61 i686 BIT64 61 x86 64 all clean ifeq ARCH BIT64 64 echo x86 64 make Su
  • linux多行注释

    1 多行注释 xff1a 1 首先按esc进入命令行模式下 xff0c 按下Ctrl 43 v xff0c 进入列 xff08 也叫区块 xff09 模式 2 在行首使用上下键选择需要注释的多行 3 按下键盘 xff08 大写 xff09
  • linux多线程信号处理

    在linux下 xff0c 每个进程都有自己的signal mask xff0c 这个信号掩码指定哪个信号被阻塞 xff0c 哪个不会被阻塞 xff0c 通常用调用sigmask来处理 同时每个进程还有自己的signal action xf
  • Mysql的row_format

    问题描述 xff1a You have an error in your SQL syntax check the manual that corresponds to your MySQL server version for the r
  • MetricsSystem

    Metrics xff0c 我们听到的太多了 xff0c 熟悉大数据系统的不可能没听说过metrics xff0c 当我们需要为某个系统某个服务做监控 做统计 xff0c 就需要用到Metrics 举个例子 xff0c 一个图片压缩服务 x
  • RecyclerView的使用(二):添加头部和尾部

    前言 Recyclerview作为Android的常用控件之一 xff0c 相信大家对它应该是十分熟悉了 xff0c 不熟悉的朋友可以参考我之前发的文章 RecyclerView的基本使用 xff0c 其中包括有单item及多Item的基本