Android RecyclerView实现吸顶动态效果,附详细效果图

news2024/11/26 9:38:30

文章目录

    • 一、ItemDecoration
    • 二、实现RecyclerView吸顶效果
      • 1、实现一个简单的RecyclerView
      • 2、通过ItemDecoration画分割线
      • 3、画出每个分组的组名
      • 4、实现吸顶效果
    • 完整demo

链接:https://download.csdn.net/download/JasonXu94/87786702
202212220944467

一、ItemDecoration

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yinKVw8W-1684338638199)(null)]ItemDecoration 允许应用给具体的
View 添加具体的图画或者 layout 的偏移,对于绘制 View之间的分割线,视觉分组边界等等是非常有用的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tV6bsdW-1684338638181)(null)]当我们调用 addItemDecoration()
方法添加 decoration 的时候,RecyclerView 就会调用该类的 onDraw 方法去绘制分割线,也就是说:分割线是绘制出来的。

RecyclerView.addItemDecoration()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QbCX4qeB-1684338638228)(null)]RecyclerView.ItemDecoration,该类为抽象类,官方目前只提供了一个实现类
DividerItemDecoration。

public abstract static class ItemDecoration

public class DividerItemDecoration extends RecyclerView.ItemDecoration

里面有3个方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PF6v7Oky-1684338638211)(null)]onDraw():
在提供给RecyclerView的画布上绘制任何适当的装饰。通过此方法绘制的任何内容都将在绘制项目视图之前被绘制,因此将出现在视图的下方。

public void onDraw(Canvas c, RecyclerView parent, State state) {
            onDraw(c, parent);
        }

绘制效果

image-20230516164805173

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oI7eqZd6-1684338638249)(null)]onDrawOver():在提供给RecyclerView的画布上绘制任何适当的装饰。通过这种方法绘制的任何内容都将在项目视图被绘制之后被绘制,因此将出现在视图上方。

public void onDrawOver(Canvas c, RecyclerView parent, State state) {
            onDrawOver(c, parent);
        }

绘制效果

image-20230516164822315

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sDcBvRbp-1684338638239)(null)]getItemOffsets():检索给定项的任何偏移量。outRect的每个字段指定项目视图应该插入的像素数,类似于padding或margin。默认实现将outRect的界限设置为0,并返回。

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state) {
            getItemOffsets(outRect, ((LayoutParams)view.getLayoutParams()).getViewLayoutPosition(),
                    parent);
        }

二、实现RecyclerView吸顶效果

1、实现一个简单的RecyclerView

下面这个RecyclerView的实现细节略。

image-20230516164844439

2、通过ItemDecoration画分割线

自定义ItemDecoration。

创建 fruitDecotion 类 继承 ItemDecoration,并实现onDraw、onDrawover、getItemOffsets三个方法。

RecyclerView调用自定义的fruitDecoration

RecyclerView.addItemDecoration(new fruitDecoration(this))

在getItemOffsets画分割线,当是组名时,预留更大的空间(即分割线的height比普通分割线大)。

@Override
    public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (parent.getAdapter() instanceof fruitAdapter){
            // parent.getAdapter()获取到当前RecyclerView的Adapter
            fruitAdapter adapter = (fruitAdapter) parent.getAdapter();
            // 获取当前view的位置
            int position = parent.getChildLayoutPosition(view);
            if (adapter.isGroupHeader(position)) {
                // 如果是头部,则预留更大的地方
                outRect.set(0, groupHeaderHeight, 0, 0);
            }else {
                outRect.set(0, 4, 0, 0);
            }
        }

实现效果

2022122209445211

3、画出每个分组的组名

当是组名时,在较大分割线哪里画出组名。在onDraw()方法里实现

@Override
    public void onDraw(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.onDraw(c, parent, state);
        if (parent.getAdapter() instanceof fruitAdapter) {
            fruitAdapter adapter = (fruitAdapter) parent.getAdapter();
            //当前屏幕中item的个数
            int count = parent.getChildCount();
            // 获取当前RecyclerView距离屏幕左边的padding
            int left = parent.getPaddingLeft();
            // right == RecyclerView的宽度 - RecyclerView的右padding
            int right = parent.getWidth() - parent.getPaddingRight();
            for (int i = 0; i < count; i++) {
                //获取对应 i 的 view
                View view = parent.getChildAt(i);
                // 获取 i 的 view 的布局位置
                int position = parent.getChildLayoutPosition(view);
                // 判断是否是头部
                boolean isGroupHeader = adapter.isGroupHeader(position);
                // i 的 view 是头部并且 当前view的top位置距离屏幕的顶部还有距离
                if(isGroupHeader && view.getTop() - groupHeaderHeight - parent.getPaddingTop() >=0) {
                    c.drawRect(left, view.getTop() - groupHeaderHeight, right, view.getTop(), headPaint);
                    String groupName = adapter.getGroupName(position);
                    textPaint.getTextBounds(groupName, 0, groupName.length(), textRect);
                    c.drawText(groupName, left + 20, view.getTop() - groupHeaderHeight / 2f + textRect.height() / 2f, textPaint);
                }else if(view.getTop() - groupHeaderHeight - parent.getPaddingTop() >=0){
                    //分割线
                    c.drawRect(left, view.getTop() - 4, right, view.getTop(), headPaint);
                }
            }
       }
    }

实现效果

image-20230516164935046

4、实现吸顶效果

因为onDrawOver方法是在itemView画了之后才画,所以组名的吸顶是写在onDrawOver方法里。需要注意的时,当我们的第二个组名到顶部的时候,要把当前顶部的组名给替换掉。

 @Override
    public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
        super.onDrawOver(c, parent, state);
        if (parent.getAdapter() instanceof fruitAdapter) {
            fruitAdapter adapter = (fruitAdapter) parent.getAdapter();
            //TODO 返回可见区域内的第一个item的position
            int position =((LinearLayoutManager) parent.getLayoutManager()).findFirstVisibleItemPosition();
            // 获取第一个item的view
            View itemView = parent.findViewHolderForAdapterPosition(position).itemView;
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
            int top = parent.getPaddingTop();
            //TODO 当第二个是头部时,
            boolean isGroupHeader = adapter.isGroupHeader(position + 1);
            if (isGroupHeader) {
                int bottom = Math.min(groupHeaderHeight, itemView.getBottom() - parent.getPaddingTop());
                c.drawRect(left, top, right, top + bottom, headPaint);
                String groupName = adapter.getGroupName(position);
                textPaint.getTextBounds(groupName, 0, groupName.length(), textRect);
                c.drawText(groupName, left + 20, top + bottom - groupHeaderHeight / 2f
                        + textRect.height() / 2f, textPaint);
            }else { // 如果不是头部, 即普通的itemView,则当前的头部一直固定在顶部
                c.drawRect(left, top, right, top + groupHeaderHeight, headPaint);;
                String groupName = adapter.getGroupName(position);
                textPaint.getTextBounds(groupName, 0, groupName.length(), textRect);
                c.drawText(groupName, left + 20, top + groupHeaderHeight / 2f
                        + textRect.height() / 2f, textPaint);
            }
        }
    }

实现效果

image-20230516164951564

完整demo

链接:https://download.csdn.net/download/JasonXu94/87786702

到此这篇关于Android RecyclerView实现吸顶动态效果流程分析的文章就介绍到这了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/538813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringDataRedis

SpringDataRedis SpringDataRedis简介RedisTemplate对Redis操作类型SpringDataRedis快速入门1、引入spring-boot-starter-data-redis依赖2、在application.properties配置Redis信息3、注入RedisTemplate并测试 SpringDataRedis的序列化方式现象分析SpringDataRedis的序列化方式…

基于RK3588的以太网PHY的问题分析

环境:RK3588为荣品电子核心板,PHY为裕太微电子YT8521; 首先上电后识别不到以太网: 1.先怀疑驱动的问题,因为本方案中直接使用的是荣品电子官方的驱动; 对比原理图及驱动。涉及到一个配置问题。 基于时钟来源的不通,驱动程序可分为四种模式,PHY的时钟和TXCLK的时钟;…

北华大学第九届程序设计竞赛 题解

5.14和队友VP一场&#xff0c;第二次VP&#xff0c;状态明显比第一次好很多&#xff0c;总共A了7题&#xff0c;基本是能做出来的都做出来了&#xff0c;最后还剩下接近2小时的时间。。。。。 A "北华"有几何 思路&#xff1a;数图片中“北华”的数量&#xff0c;直…

双平台GraalVM编译二进制程序

本文示例均采用Java11&#xff0c;GraalVM目前无法支持跨平台编译&#xff0c;比如&#xff0c;我通过Linux直接编译Windows可执行的exe&#xff0c;是不行的。 因此&#xff0c;需要掌握两种平台的GraalVM的安装、使用。 一、背景 1.1 为何GraalVM快&#xff1f; 常规Java…

永恒之塔私服 2.0包楼纳斯达克 网游的诺曼底登陆-

二战末期的诺曼底登陆&#xff0c;至今让人历历在目。盟军自此在西欧展开大规模进攻&#xff0c;加速了纳粹德国的崩溃。从某种意义上说&#xff0c;诺曼底登陆是整个二战一次生死攸关的转折点。《永恒之塔2.0&#xff1a;进军龙界》登上纳斯达克&#xff0c;也是一场激荡人心的…

基于自动编码器VAE的声音生成之音频预处理模块preprocess pipeline的实现和代码讲解

文章目录 概述Preprocessline模块实现以及代码讲解Loader模块Padder模块LogSpectrogramExtractor模块MinMaxNormaliser模块Saver模块PreprocessPipeLine模块知识补充property修饰词 总结 概述 这部分是将原来基于mnist手写数据集生成模型&#xff0c;一个用到基于FSDD音频数据…

蓝桥:前端开发笔面必刷题——Day2 数组(二)

文章目录 &#x1f4cb;前言&#x1f3af;删除有序数组中的重复项&#x1f4da;题目内容✅解答 &#x1f3af;移动零&#x1f4da;题目内容✅解答 &#x1f3af;长度最小的子数组&#x1f4da;题目内容✅解答 &#x1f3af;反转字符串数组&#x1f4da;题目内容✅解答 &#x1…

麒麟操作系统软件更新灾难连篇之二:QQ罢工

在解决了中文输入法消失的问题后&#xff0c;还没缓过气来&#xff0c;又发现QQ罢工了&#xff1a;双击电脑桌面上的QQ图标&#xff0c;没有显示QQ登录界面。 重启电脑再试&#xff0c;还是不显示QQ登录界面。 前不久腾讯正式宣布&#xff0c;QQ Linux 版 3.0 已在 QQ 官网上…

最好用的文本与文件查询软件AnyTXT Searcher与Listary简介

1. 工具简介 1.1 Listary简介 Listary是一个革命性的Windows搜索工具&#xff0c;借助 Listary软件&#xff0c;你可以快速搜索电脑文件、定位文件、执行智能命令、记录访问历史、快速切换目录、收藏常用项目等。 Listary为Windows传统低效的文件打开/保存对话框提供了便捷、…

Apache Tomcat AJP协议文件读取与包含

永远也不要忘记能够笑的坚强&#xff0c;就算受伤&#xff0c;我也从不彷徨。 0x01.漏洞情况分析 Tomcat是Apache软件基金会Jakarta 项目中的一个核心项目&#xff0c;作为目前比较流行的Web应用服务器&#xff0c;深受Java爱好者的喜爱&#xff0c;并得到了部分软件开发商的…

makefile 学习(2):C语言的编译及库文件的生成与链接

文章目录 1. 介绍2. C语言编译2.1 预处理2.2 生成汇编语言2.3 编译目标文件2.4 编译为可执行文件 3. .a静态库的编译与链接案例 4 .so 动态库的编译与链接 1. 介绍 编译C语言的相关后缀 .a 文件是一个静态库文件.c文件是c语言的源文件.h c语言的头文件.i 是预处理文件.o 目标文…

两个用字符串表示的大数字的和

文章目录 题目详情Java实现分析Java 怎么获取到字符串中的对应位置的数字值Java完整代码测试验证 python实现python 怎么获取到字符串中的对应位置的数字值python完整代码 总结 这是遇到的一道快手数仓岗位的面试题目&#xff0c;题目大意如下&#xff1a; 题目详情 现在有两个…

【树莓派4B安装18.04桌面+远程SSH】

【树莓派4B安装18.04桌面远程SSH】 1. 前言2 .树莓派安装ubuntu18.04 系统2.1 下载ubuntu Server 18.04 的镜像包2.2 镜像烧录2.3 高级设置2.4 配置WiFi2.5 ssh文件配置2.6 Pi 4B启动文件 3. 安装finalshell3.1 windows版下载3.2 windows版安装3.3 SSH连接 4. 安装ubuntu桌面4.…

【野火启明_瑞萨RA6M5】梦的开始 ---- 点灯(寄存器)

文章目录 一、IOPORT简介二、IOPORT的框图分析三、IOPORT的寄存器描述1. 端口引脚功能选择寄存器2. 端口输出数据寄存器3. 端口输入数据寄存器4. 端口输出置位/复位寄存器5. 写保护寄存器 四、点亮LED灯&#xff08;寄存器&#xff09; 从本文开始&#xff0c;我将以瑞萨RA系列…

【夜莺(Flashcat)V6监控】3.链路追踪

链路追踪 介绍 链路追踪是分布式系统下的一个概念&#xff0c;它的目的就是要解决上面所提出的问题&#xff0c;也就是将一次分布式请求还原成调用链路&#xff0c;将一次分布式请求的调用情况集中展示&#xff0c;比如&#xff0c;各个服务节点上的耗时、请求具体到达哪台机…

Java 把一个 List 转换为字符串

在本快速指南中&#xff0c;我们将会解释如何在 Java 把一个 List 转换为 String 字符串。 这个在某些特定的场合可能比较有用&#xff0c;比如说在控制台中输出 List 中的内容&#xff0c;转换为可以人为阅读的内容来进行调试。 使用 List 中标准的 toString() 方法 一个最简…

(2)数码管

LED数码管:数码管是一种简单、廉价的显示器&#xff0c;是由多个发光二极管封装在一起组成"8"字器件 51单片机是共阴极连接 74HC245这个芯片有什么作用呢&#xff1f;解&#xff1a;这个芯片被称之为双向数据缓冲器这个芯片的作用&#xff0c;用来进行数据缓冲(提高驱…

【网络编程】详解UDP/TCP套接字的创建流程

目录 一、网络编程套接字 1、一些概念 1.1源IP地址和目的IP地址 1.2端口号port 1.3TCP和UDP的性质 1.4网络字节序、IP地址类型转换、数据接收与发送函数、popen函数 2、UDP套接字 2.1UDP服务器创建流程 2.2UDP客户端创建流程 2.3创建socket套接字 2.4绑定套接字对应…

快速找出PATH 路径下重复的命令程序文件

RT&#xff0c;就是想找出命名冲突的可执行文件。日积月累的&#xff0c;PATH 环境变量里乱七八糟堆了一堆东西&#xff0c;很可能想叫一个命令出来&#xff0c;结果实际执行的是另一个地方的程序。 Python 脚本 import ospath os.environ[PATH] folders path.split(;) fil…

理解HttpSession

什么是session 在我刚刚从事后端开发的时候&#xff0c;有一个问题困扰了我很久。 就有个玩意叫session。 PostMapping("login")public Result login(RequestParam("id") String id,RequestParam("password") String password, HttpSession se…