RecyclerView Item 的悬浮效果(吸附效果)的实现

Android Swipe-to-Delete 生产级实现:手势、快照与Undo闭环设计 Swipe-to-Delete 是 Android 列表交互的基础能力,其本质是手势识别、UI 状态同步与业务数据变更的协同机制。原理上依赖 ItemTouchHelper 的事件拦截与状态机驱动,但默认配置易受设备密度、嵌套滚动和 RTL 布局影响,需动态调优滑动阈值与位移逻辑。技术价值在于将瞬时操作转化为可逆、幂等、带生命周期管理的数据命令,避免索引漂移与状态丢失;典型应用场景涵盖电商订单、笔记列表、审批任务等涉及软删除的真实业务。本文聚焦 RecyclerView 场景下从手势稳定性、DeleteCo 阅读详情

参考文章:Android 轻松实现 RecyclerView 悬浮条

本例源码:https://github.com/374901588/RVSuspensionBarTest


在参考文章中,实现的是如下效果:
这里写图片描述

实现的基本原理就是在一个 FrameLayout 中,设置一个 RV,然后在设置一个和 ItemView 一样布局结构以及样式的悬浮条,然后悬浮条根据条件动态设置位置。

而该文章中博主也说明了这种效果的实现方案,但那是在 RV 的 Item 只有一个层级的情况下,即所有的 ItemView 都是同一类型的,而我是在使用了 drakeet 大佬的 MultiType,实现了 数据扁平化处理:
这里写图片描述
引自:Android 复杂的列表视图新写法 MultiType

我需要让下图的 RV 也实现那种效果:
这里写图片描述
虽然存在 Post 和 Comment 两种类型的 ItemView,但是由于扁平化的处理,两种 ItemView 都处于同一层次结构,而不是嵌套的关系。即两种 ItemView 都 RV 的直接 ItemView,并且其中某些 Post 类型的 ItemView 可能会不存在附属的 Comment ItemView。这种情况下,如果完全按照参考文章的那种实现方法的话,则会得不到预期的效果,下图为预期效果图:
这里写图片描述

当然,主要的思想根据原参考文章的类似,但是在一些细节方面就需要做一下修改,这本例的实现中,RV 的两种 ItemView 都是一个简答的 TextView,只不过是在 Adapter 中动态设置样式而已,因此悬浮条也是一个简单的 TextView,且高度、样式都要与 Post ItemView 的样式一样。

然后下面是核心代码,说明也依附在代码注释上了,其中 mCurrentPosition 初始值为 0,因为在本次演示中不存在 HraderView,如果存在的话,则 mCurrentPosition 初始值应为第一个 Post ItemView 的 position:

rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) rv.getLayoutManager();
            int mSuspensionHeight;

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

				// mSuspensionBar.getHeight()的高度的获取如果是在 onCreate() 或者是
				// 在 RecyclerView.OnScrollListener 被初始化的时候去获取,获得的结果
				// 会为 0,因此此时 mSuspensionBar 还没有初始化完成               
				mSuspensionHeight = mSuspensionBar.getHeight();

                int firstVisPos = linearLayoutManager.findFirstVisibleItemPosition();

                Object firstVisibleItem = items.get(firstVisPos);
                Object nextItem = items.get(firstVisPos + 1);
                View nextView = linearLayoutManager.findViewByPosition(firstVisPos + 1);

				//下滑情况下
                if (dy > 0) {
	                //只有第一个可见的 Item 的下一个 Item 的类型
	                //为 Post类型时才需要动态设置效果
                    if (nextItem instanceof Post) {

                        if (nextView.getTop() <= mSuspensionHeight) {
                            //被顶掉的效果
                            mSuspensionBar.setY(-(mSuspensionHeight - nextView.getTop()));
                        } else {
	                        //否则就直接回到 Y = 0 的位置
                            mSuspensionBar.setY(0);
                        }
                    }

                    //判断是否需要更新悬浮条
                    if (mCurrentPosition != firstVisPos && firstVisibleItem instanceof Post) {
                        mCurrentPosition = firstVisPos;
                        //根据 mCurrentPosition 的值,更新 mSuspensionBar
                        updateSuspensionBar();
                        mSuspensionBar.setY(0);
                    }
                } else {//上滑情况
                    // 1、nextItem -> Post and firstVisibleItem -> Comment       mCurrentPosition = ((Comment) firstVisibleItem).getParentPostPosition()
                    // 2、nextItem -> Post and firstVisibleItem -> Post          mCurrentPosition = firstVisPos
                    // 3、nextItem -> Comment and firstVisibleItem -> Comment    mSuspensionBar 不动
                    // 4、nextItem -> Comment and firstVisibleItem -> Post       mSuspensionBar 不动
                    if (nextItem instanceof Post) {
                        mCurrentPosition = firstVisibleItem instanceof Post ? firstVisPos : ((Comment) firstVisibleItem).getParentPostPosition();
                        updateSuspensionBar();

                        if (nextView.getTop() <= mSuspensionHeight) {
                            //被顶掉的效果
                            mSuspensionBar.setY(-(mSuspensionHeight - nextView.getTop()));
                        } else {
                            mSuspensionBar.setY(0);
                        }
                    }
                }
            }
        });

如果对于上面的代码有所疑惑,其实可以将 mSuspensionBar 的背景设置为不同的颜色,同时设置一下透明度,就可以看到其原本的运作状态了,如下图,其中 mSuspensionBar.setY(0) 时当效果尤为明显:
这里写图片描述

其中,较为特殊的就是上滑的情况了,在上面的代码注释中也有说明,上滑时总共有四种情况:

1、nextItem -> Post and firstVisibleItem -> Comment       mCurrentPosition = ((Comment) firstVisibleItem).getParentPostPosition()
2、nextItem -> Post and firstVisibleItem -> Post          mCurrentPosition = firstVisPos
3、nextItem -> Comment and firstVisibleItem -> Comment    mSuspensionBar 不动
4、nextItem -> Comment and firstVisibleItem -> Post       mSuspensionBar 不动

其中 -> 符号表示该 Item 对应的具体类型,只有头两种情况下,mSuspensionBar 才需要根据具体的情况设置动态效果,剩下的两种情况下只要固定不动就可以了。

还需要说明的是,当 nextItem -> Post and firstVisibleItem -> Comment 时,正常情况是无法知道第一个可见 Item (即 firstVisibleItem )所附属于的 Post 的 position,因此需要在初始化这些 Comment Item 的时候就设置好其附属于的 Post 的 position,然后动态获取。

就像下面的代码,会在初始化 Comment 元素时为其设置所附属的 Post 的 position:

//模拟数据
List<Post> list = new ArrayList<>();
int index = 0;
int parentPostPos;
Random random = new Random();
for (int i = 0; i < 10; i++) {
    Post post = new Post("pos = " + index);
    parentPostPos = index;
    list.add(post);
    index++;
    int k = random.nextInt(5);
    post.comments = new ArrayList<>();
    for (int j = 0; j < k; j++) {
        Comment comment = new Comment("pos = " + index, parentPostPos);
        post.comments.add(comment);
        index++;
    }
}

最后,再推荐一篇实现本文效果的文章:

RecyclerView 使用ItemDecoration 巧妙实现吸附效果

在该篇文章中的实现,是利用了 recyclerView.addItemDecoration() 来自定义 ItemDecoration 实现的效果,这种方式实现了与业务的解耦,但在具体实现上相比上面的实现更加复杂一点,而且在遇到第三方的涉及 RV 的框架时,就可能需要根据具体的框架去进行相应的修改了,如在使用 MultiType 时,就不是那么好契合了。

Android滑动吸附悬停技术与实现 ViewPager 是 Android 开发中常用的组件,用于实现滑动页面切换的效果。它的核心是一个适配器模式,通过内部的Adapter来承载和管理多个页面视图。使用ViewPager时,开发者需要为其设置一个Adapter,Adapter会负责创建与ViewPager页面数量一致的视图(View)。关键API包括:: 设置页面适配器。: 设置ViewPager当前显示的页面。: 设置预加载的页面数量,以优化性能。ViewPager内部默认不支持滑动吸附。 阅读详情

相关推荐

RecyclerView 使用ItemDecoration 巧妙实现吸附效果

方便自己查找!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

实现带悬浮条的RecycleView,可能没你想象的那么复杂!

前言 主要思路是为RecycleView添加addOnScrollListener监听,然后改变悬浮条的位置即可实现。 提示:以下是本篇文章正文内容 代码如下(示例): 主要代码如下(示例): mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView

让技术为我所用 528

Android 开源之StickyHeaderListView 标题渐变、吸附悬停、筛选分类、动态头部

Android 开源之StickyHeaderListView 标题渐变、吸附悬停、筛选分类、动态头部,http://www.jianshu.com/p/3bf26722c489#

Android CoordinatorLayout进阶教程-RecyclerView悬停效果

这里,当 RecyclerView上拉时会先滑动AppBarLayout从而悬停滑动固定区域,然后再继续RecyclerView视图自己的滑动事件,下拉时会先实现RecyclerView自己的滑动事件,当RecyclerView第一个item全部显示后滑动事件会传递给AppBarLayout,从而展示滑动隐藏区域。话不多说,我们先来看一下我们实现的效果。我们来看一下视图布局代码以及类代码。Activity代码。

aaaym的博客 1098

OV5640摄像头DVP与MIPI接口配置实战:从30Hz到60Hz的性能优化指南

本文详细解析了OV5640摄像头在DVP与MIPI接口下的60Hz性能优化方法,重点解决720p分辨率下帧率仅30Hz的常见问题。通过精确配置时钟树、传感器寄存器和接口参数,提供DVP与MIPI接口的实战配置代码,并分享调试工具与性能验证技巧,帮助开发者实现稳定的60fps输出。

weixin_29223603的博客 1301

MAX30102心率血样模块在STM32F103芯片的程序说明

我希望你已经安装好了Keil MDK5这个软件,也安装了M3内核,可以编译一些STM32F103的一些项目下载程序后步骤: 1-按照下图找到IIC.uvprojx并打开(途中唯一绿色那个图标) 2-编译一次 3-确保0错误,0警告,下图所示 4-点击目标选项,然后找到STM32F103C8,再点debug–CMSIS****(我实际用的JTAG,用不了,选择这个CMSIS****即可)下图所示 5-下图所示,看看你的串口找到了没,找到了就点左下角的OK 6-按图上传到开发板 7-MAX30102接线方法

weixin_51357422的博客 5801

【Android -- UI 开发】RecyclerView 实现顶部悬浮效果

本文介绍了 Android RecyclerView 悬浮效果

Kevin Learn Android 1746

Spring Boot应用Docker化实战:从Dockerfile编写到镜像推送完整流程

本文详细介绍了将Spring Boot应用Docker化的完整实战流程。从环境准备、项目审视,到编写高效且安全的Dockerfile,重点讲解了多阶段构建、镜像层优化、Spring Boot分层JAR等核心技巧,并涵盖了镜像构建、验证、调试以及最终推送至仓库并集成CI/CD的最佳实践,帮助开发者构建生产级Docker镜像。

butter的博客 1023

RecyclerView 悬浮/粘性头部效果3种方式

总结下RecyclerView 悬浮/粘性头部实现的3种方式: 1,xml布局中设定悬浮/粘性头部view,在RecyclerView滑动过程中动态修改其位置; 参考:https://www.diycode.cc/topics/408 2,ItemDecoration 实现(高耦合) 参考:https://blog.youkuaiyun.com/qian520ao/article/details/76...

lifs419的博客 2954

海康/大华设备如何接入GB28181平台?最新2022版互联避坑指南

本文详细解析了海康/大华设备接入GB28181平台的最新2022版互联避坑指南,涵盖参数配置、实时视音频点播协议交互及典型故障排查。重点介绍了GB/T28181-2022标准下的设备编码规范、SIP服务器配置及媒体流保活机制,帮助工程团队高效解决设备离线和媒体流中断等问题。

weixin_30733003的博客 687

疾风气象大模型4.0白皮书

《疾风气象大模型白皮书摘要》 疾风气象大模型(J-AFM)是国内首个基于3D建模的气象智能平台,突破传统二维气象分析的局限,采用体素化技术构建"x-y-z-t"四维统一模型,实现从分钟级短临到30天跨时效的连续预测。核心技术包括:1)多源数据三维同化,融合雷达、卫星、风廓线等异构数据;2)物理约束AI解码器,嵌入能量守恒、湍流封闭等气象原理;3)行业适配插件,服务风电、光伏、航空等领域,如山地风场尾流校正、云影短临预测。平台支持批流一体推理与边缘部署,提供概率化输出和误差溯源能力,显著降

专注AI大模型,软件混淆,授权 542

Android -- RecyclerView实现顶部吸附效果

1,先来看一下今天实现的效果: 2,这次的效果是使用ItemDecoration来实践的,来看一看我们的实现吧   第一步:首先添加依赖,由于我们这些数据是请求网络的,所以一下我们添加网络框架依赖、RecyclerView、Glide依赖 apply plugin: 'com.android.application' apply plugin: 'com.neenbedankt.a

狼啸极行的博客 891

手机VPN的连接方法分享

6、返回到VPN页面,可以看到刚刚新添加的VPN,点击开启VPN后面的开关。5、在打开的添加VPN的页面中输入VPN的信息后点击右上角的“保存”按钮。7、待VPN开关开启后,可以看到添加的VPN正在连接的提示信息了。2、在打开的小米手机设置页面中点击“更多连接方式”的菜单项。3、然后在打开的更多连接方式页面中点击VPN的菜单项。4、在打开的VPN设置页面中点击“添加VPN”的按钮。1、首先在手机屏幕左右的滑动,找到手机的设置图标。

惠惠软件 3万+

recycleview中单个item上滑到顶部后悬停顶部的功能实现

需求背景 需要将列表中的第二个子view在滑动到顶端之后悬停在顶部,下拉之后取消悬停顶部,实现后效果如下图中所示,当上滑时候需要将列表中的综合销量价格选择栏目固定在顶部,当下拉后恢复列表中位置 实现过程: 看到这样的需求首先想到的一个词就是recycleview顶部吸附效果,在大略查找recycleview可用方法之后,发现没有这样的方法可以直接使用,google之后搜索到很多相似内容,都是st...

搬砖的老牛 1405

WblockCloneObjects克隆一个图纸内的实体包括块参照,同名块参照的处理

public static void HeBingTu2(double lieJu, List<string> filePaths) { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; using (DocumentLock docLock = doc.Lock...

1108

基于 51 单片机的智能手势控制小车设计与实现

智能手势控制小车以STC89C52RC 单片机为控制核心,通过手势识别模块采集用户手势指令,经单片机处理后驱动电机执行前进、后退、左转、右转等动作。该项目融合了传感器技术、单片机编程和电机驱动技术,具有成本低、易实现、互动性强的特点,适合作为嵌入式系统入门实践案例。本项目成功实现了基于 51 单片机的智能手势控制小车,通过 APDS-9960 模块采集手势信号,经单片机处理后驱动电机完成基本动作,验证了 “传感器 + 单片机 + 执行器” 的嵌入式系统设计思路。

weixin_42300449的博客 178

RecyclerView -- 中阶

BRVAH使用多布局 1. 实体类实现MultiItemEntity 接口,根据类型进行绑定; 2. 为 BaseQuickAdapter 设置代理。标题SnapHelper Support RecyclerView 24.2.0中新加,让RecyclerView滑动视图后使停止位置正好停在某页的正中间。new LinearSnapHelper().attachToRecyclerView(r

ThePromonkeyOf_HeLuo的博客 378

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android 开源项目分类汇总(android-open-project)完整指南:个性化控件、工具库与开发测试工具全景索引

android-open-project 是一个**分类汇总型的 Android 开源项目索引仓库**,其价值不在于提供可运行的源码,而在于用一套清晰、可检索的分类体系,把海量第三方开源项目按"控件 → 库 → 项目 → 工具 → 人"的维度组织起来。 从 [docs/oss-program-readiness.md](https://link.gitcode.com/i/c52df8b982c

gitblog_00983的博客 438

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

第 4 章 · 状态与重组:Compose 的心脏(上篇)

本章是Compose学习的分水岭,核心在于理解“状态如何驱动界面更新”。与View体系手动刷新不同,Compose通过mutableStateOf等机制实现状态可观察,状态变更自动触发重组。掌握remember、状态稳定性、重组作用域及快照系统等11个关键点,才能精准控制界面更新时机,避免无效重组或更新失效。吃透本章,后续开发才有坚实抓手。

不忘初心 325

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

android头部固定悬停,Android RecyclerView实现头部悬浮吸顶效果

之前我在GitHub上开源了一个可以实现RecyclerView列表分组的通用Adapter:为了给RecyclerView实现头部悬浮的功能,我在GroupedRecyclerViewAdapter框架里添加了一个StickyHeaderLayout控件,由StickyHeaderLayout实现头部悬浮效果并且管理悬浮吸顶的View。下面我会给出StickyHeaderLayout源码,我在源...

weixin_36302350的博客 1652

RecyclerView实现吸顶效果

RecyclerView实现吸顶效果

QG 481

【Android 技术难点攻克】RecyclerView实现悬停导航栏

介绍 在上一篇文章《彻底解决RecyclerView与ScrollView滑动冲突问题,并实现RecyclerView悬停导航栏》中,我讲述了如何解决ScrollView与RecyclerView的滑动冲突问题。时隔几个月,我对这样的程序结构有很多的反思。当初这样嵌套,其实最主要是为了实现悬停。那么悬停的最好的实现方式就是这样去解决滑动冲突吗? 答案或许是否。当然,几个月前,我设计出Scr...

你关注了我,是个概率极低的事件...... 6931

Android ItemTouchHelper实现RecyclerView交互动画

在上一次博客 Android RecyclerView使用详解,主要介绍了RecyclerView的基础使用,本篇文章将主要介绍通过ItemToucheHelper辅助类完成RecyclerView的交互动画效果。 效果如下: ItemTouchHelper简单使用 要想通过ItemTouchHelper实现交互动画,只需要以下步骤: 定义一个ItemTouchHelper.C

zhangke 4604

Android RecyclerView字母索引,一行代码实现吸顶效果,简单实用,附demo地址和截图

分享一个实用的列表吸顶效果 demo源码地址 字母索引,列表吸顶 效果图 核心代码 ```java package com.laj.wxaddperson.hover_item; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.util.TypedValue; import

y1010012836的博客 1560

android+recyclerview悬停动画,Android RecyclerView实现悬浮吸顶、分隔线、到底提示效果...

本文中所有效果通过ItemDecoration实现,通过此实现的可以与业务解耦,让RecyclerView的模板更加简洁,不关心任何辅助性ui,github地址一、顶部吸附效果图二、顶部不吸附效果图三、不满一屏效果四、核心实现点1、为什么通过ItemDecoration能够实现,原理?①通过getItemOffsets()方法获取当前模板view的left、top、right、bottom边距,这...

weixin_30840919的博客 497
上一篇: 《Android 复杂的列表视图新写法 MultiType》知识点整理
下一篇: RxJava2 学习笔记 (二)
OneDeveloper
博客等级 码龄9年 61粉丝 161原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值