Android进阶之路 - RecyclerView停止滑动后Item自动居中(SnapHelper辅助类)
之前一直没注意
SnapHelper
辅助类的功能,去年的时候看到项目中仅通过俩行代码设置RecyclerView
后就提升了用户体验,觉得还是很有必要了解一下,尝试过后才发现其PagerSnapHelper
、LinearSnapHelper
子类可以作用于不同场景,且听吾言
RecyclerView基础
- Android进阶之路 - RecyclerView基础使用(17年)
- Android进阶之路 - RecyclerView实现横、纵向滑动列表(19年)
- Android基础进阶 - RecyclerView列表加载多类型视图
RecyclerView扩展
- Android进阶之路 - RecyclerView加载多类型视图(ConcatAdapter到底有没有学习必要?)
- Android进阶之路 - RecyclerView停止滑动后Item自动居中(SnapHelper辅助类)
RecyclerView相关功能
- Android进阶之路 - RecyclerView左划删除(SwipeRecyclerView的简单使用 17年)
- Android进阶之路 - RecyclerView列表置顶、滑动到指定条目(18年)
- Android进阶之路 - RecyclerView列表自动无限水平滚动(21年)
- Android进阶之路 - 双列表联动效果(18年)
他字字未提喜欢你,你句句都是我愿意
- 基础了解
- 实践检验
- 前置 ItemView
- 前置 Adapter
- 使用方式
你在开发项目中遇到过这样的场景吗?
Hint:
RecyclerView
为水平滑动 && 子ItemView
宽度非match_parent
(支持同屏展示多个ItemView
)
- 用户滑动列表时产生类似
ViewPager
效果,停止滑动后ItemView
自动居中(一般正常速度滑动只滑动一条数据,但是当滑动速度加快(比较费力时),可能会滑动多条数据
) - 用户正常速度滑动列表时可更轻易的滑动多条数据,停止滑动后子
ItemView
自动居中
Look效果:如果以下效果不能完全满足,也可以自定义SnapHelper
,然后参考其子类实现增添部分你需要的业务功能,例如修改滑动速度等
Tip
:核心方法仅有俩行,如急于开发,亦可直接使用或直接看实践检验
,等有时间再来一同了解
创建对应的 SnapHelper
后通过 attachToRecyclerView
关联 RecyclerView
即可
- PagerSnapHelper
val pagerSnapHelper = PagerSnapHelper()pagerSnapHelper.attachToRecyclerView(mRvPager)
- LinearSnapHelper
val lineaSnapHelper = LinearSnapHelper()lineaSnapHelper.attachToRecyclerView(mRvLinear)
基础了解
SnapHelper
自身为抽象类,同时继承了RecyclerView.OnFlingListener
,内部实现了一些通用基类方法,you俩个实现子类,通过重写其中部分方法,从而达到对应的需求效果
PagerSnapHelper
:类似ViewPager
滑动效果,仅支持单条滑动!在ViewPager
控件中也可以看到PagerSnapHelper
的身影LinearSnapHelp
:水平快速滑动列表,体验丝滑,当滑动停止后,ItemView
自动居中
OnFlingListener
仅拥有一个抽象方法
因为我只是通过源码方法命名 + 参考方法注释 简单理解,可能并不是很详细,有兴趣的可以前往早期一位前辈写的 让你明明白白的使用RecyclerView——SnapHelper详解
通过查看 SnapHelper
内部方法,简单分析一下方法作用范围(仅做部分解释,并不完全)
- 支持
绑定RecyclerView
calculateDistanceToFinalSnap
测量移动距离findSnapView
支持定位移动的View
findTargetSnapPosition
支持定位移动后的数据(视图)角标
FlingListener
、ScrollListener
滑动监听&滑动速度监听
PagerSnapHelper
、LinearSnapHelper
除基类方法外,支持获取居中View、布局方向等
PagerSnapHelper 源码方法
LinearSnapHelper 源码方法
如果要自定义 SnapHelper
的话,需要重新以下三个抽象方法
package com.example.recyclerviewsnaphelperimport android.view.View
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SnapHelperclass OurHelper : SnapHelper() {//计算最终移动距离override fun calculateDistanceToFinalSnap(layoutManager: RecyclerView.LayoutManager, targetView: View): IntArray? {TODO("Not yet implemented")}//获取移动Viewoverride fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? {TODO("Not yet implemented")}//获取移动View的角标位置override fun findTargetSnapPosition(layoutManager: RecyclerView.LayoutManager?, velocityX: Int, velocityY: Int): Int {TODO("Not yet implemented")}
}
实践检验
RecyclerView
常规使用,仅加入了SnapHelper.attachToRecyclerView
相关绑定
前置 ItemView
item_view
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="250dp"android:layout_height="100dp"android:paddingHorizontal="5dp"><TextViewandroid:id="@+id/tv_data"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#f98741"android:gravity="center"android:text="Item Data"android:textColor="#ffffff"android:textStyle="bold" />
</androidx.appcompat.widget.LinearLayoutCompat>
前置 Adapter
package com.example.recyclerviewsnaphelperimport android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerViewclass OurAdapter(private val dataList: MutableList<String>) : RecyclerView.Adapter<OurAdapter.OurViewHolder>() {override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OurViewHolder {return OurViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_view, parent,false))}override fun getItemCount(): Int {return dataList.size}override fun onBindViewHolder(holder: OurViewHolder, position: Int) {holder.itemView.findViewById<TextView>(R.id.tv_data).text=dataList[position]}inner class OurViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
}
使用方式
package com.example.recyclerviewsnaphelperimport android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSnapHelper
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.HORIZONTALclass MainActivity : AppCompatActivity() {var dataList = mutableListOf<String>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)//数据模拟for (i in 0..15) {dataList.add("第${i + 1}页")}//RecyclerView基础配置pagerRecyclerSetting()layoutRecyclerSetting()}/*** RecyclerView基础配置:PagerSnapHelper示例* */private fun pagerRecyclerSetting() {val mRvPager = findViewById<RecyclerView>(R.id.rv_pager)var layoutManager = LinearLayoutManager(this)layoutManager.orientation = HORIZONTALmRvPager.layoutManager = layoutManagerval ourPagerAdapter = OurAdapter(dataList)mRvPager.adapter = ourPagerAdapter//添加SnapHelper相关辅助类val pagerSnapHelper = PagerSnapHelper()pagerSnapHelper.attachToRecyclerView(mRvPager)}/*** RecyclerView基础配置:LinearSnapHelper示例* */private fun layoutRecyclerSetting() {val mRvLinear = findViewById<RecyclerView>(R.id.rv_linear)var layoutManager = LinearLayoutManager(this)layoutManager.orientation = HORIZONTALmRvLinear.layoutManager = layoutManagerval ourLayoutAdapter = OurAdapter(dataList)mRvLinear.adapter = ourLayoutAdapter//添加SnapHelper相关辅助类val lineaSnapHelper = LinearSnapHelper()lineaSnapHelper.attachToRecyclerView(mRvLinear)}
}
activity_main
- 预览图
layout
布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="40dp"android:gravity="center"android:text="PagerSnapHelper效果"android:textStyle="bold" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_pager"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"tools:itemCount="10"tools:listitem="@layout/item_view" /><TextViewandroid:layout_width="match_parent"android:layout_height="40dp"android:layout_marginTop="50dp"android:gravity="center"android:text="LinearSnapHelper"android:textStyle="bold" /><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/rv_linear"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"tools:itemCount="10"tools:listitem="@layout/item_view" /></androidx.appcompat.widget.LinearLayoutCompat>
相关文章:

Android进阶之路 - RecyclerView停止滑动后Item自动居中(SnapHelper辅助类)
之前一直没注意 SnapHelper 辅助类的功能,去年的时候看到项目中仅通过俩行代码设置 RecyclerView 后就提升了用户体验,觉得还是很有必要了解一下,尝试过后才发现其 PagerSnapHelper、LinearSnapHelper 子类可以作用于不同场景,且听…...

高性能图表组件LightningChart .NET v11.0发布——增强DPI感知能力
LightningChart完全由GPU加速,并且性能经过优化,可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D,高级3D,Polar,Smith,3D饼/甜甜圈,地理地图和GIS图表以及适用于科学&am…...

神经网络系列---计算图基本原理
文章目录 计算图符号微分符号微分的步骤示例符号微分在计算图中的使用总结 数值微分前向差分法中心差分法数值微分的使用注意事项总结 自动微分1. 基本原理2. 主要类型3. 计算图4. 应用5. 工具和库6. 优点和缺点 计算图1. **计算图的建立**2. **前向传播**3. **反向传播**4. **…...

3D数字孪生
数字孪生(Digital Twin)是物理对象、流程或系统的虚拟复制品,用于监控、分析和优化现实世界的对应物。 这些数字孪生在制造、工程和城市规划等领域变得越来越重要,因为它们使我们能够在现实世界中实施改变之前模拟和测试不同的场景…...

C++惯用法之空基类优化
相关系列文章 C惯用法之Pimpl C惯用法之CRTP(奇异递归模板模式) C之std::tuple(二) : 揭秘底层实现原理 目录 1.空类 2.空基类优化 3.内存布局原则 4.实例分析 5.总结 1.空类 C 中每个对象的实例都可以通过取地址运算符获取其在内存布局中的开始位置,因此每个类…...

【生成式AI】ChatGPT 原理解析(2/3)- 预训练 Pre-train
Hung-yi Lee 课件整理 预训练得到的模型我们叫自监督学习模型(Self-supervised Learning),也叫基石模型(foundation modle)。 文章目录 机器是怎么学习的ChatGPT里面的监督学习GPT-2GPT-3和GPT-3.5GPTChatGPT支持多语言…...

Day03:Web架构OSS存储负载均衡CDN加速反向代理WAF防护
目录 WAF CDN OSS 反向代理 负载均衡 思维导图 章节知识点: 应用架构:Web/APP/云应用/三方服务/负载均衡等 安全产品:CDN/WAF/IDS/IPS/蜜罐/防火墙/杀毒等 渗透命令:文件上传下载/端口服务/Shell反弹等 抓包技术:…...

C++多线程同步(上)
多线程同步 引言总述详情互斥锁示例运行结果分析条件变量示例一实现分析优化运行结果示例二实现代码运行结果示例三实现代码运行结果读写锁示例实现代码注意分析运行结果附言实现运行结果运行结果个人心得引言 项目中使用多线程,会遇到两种问题,一种是对共享资源的访问时需要…...

猜猜心里数字(个人学习笔记黑马学习)
1.定义一个变量,数字类型,内容随意 2.基于input语句输入猜想的数字,通过if和多次elif的组合,判断猜想数字是否和心里数字一致 num5if int(input("请输入第一次猜想的数字:"))5:print("猜对了࿰…...
实用Pycharm插件
Pycharm的离线安装:https://plugins.jetbrains.com/ 需要根据对应的Pycharm/Goland版本选取所需的 对于实用的插件如下: 实时查看每一行的git blame信息: Gittoolbox 转换IDE的英文为中文:Chinese IDE侧格式化json字符串&#…...

数据结构试题练习
(1). 假如队列未满,现有变量data需要入队,请写出表达式; if( (tail1)%SEQLEN ! head ) {seqn[tail] data;tail (tail1)%SEQLEN; } (2). 假如队列未空,现在需要从队列取一个元素并赋值给变量data,请写出表达式; if( head ! tail ) {data se…...

s-table和columns初始化不完整,造成table文件的filter报错
问题 顺藤摸瓜找errorHandler.js文件 发现文件并没有什么问题 顺藤摸瓜找index.vue文件 首先找到报错的filter,发现与columnsSetting相关 找到columnsSetting发现等于columns 返回自己使用S-table组件的地方,发现columns初始化时仅初始化为ref()未表明…...
SLA 是什么?如何实现 SLA 管理
随着业务的不断壮大,为了满足日益增长的客户需求,网络必须保持与这些需求同步。同时,为了提高最终用户的体验,运维人员/网络管理员在监控企业级网络时遇到了不少瓶颈,必须不断审查网络,以确保提供的服务质量…...

火灾安全护航:火灾监测报警摄像机助力建筑安全
火灾是建筑安全中最常见也最具破坏力的灾难之一,为了及时发现火灾、减少火灾造成的损失,火灾监测报警摄像机应运而生,成为建筑防火安全的重要技术装备。 火灾监测报警摄像机采用高清晰度摄像头和智能识别系统,能够全天候监测建筑内…...

JavaScript 基础学习笔记(五):函数、作用域、匿名函数
目录 一、函数 1.1 声明和调用 1.2 形参和实参 1.3 返回值 二、作用域 2.1 全局作用域 2.2 局部作用域 三、匿名函数 3.1 函数表达式 3.2 立即执行函数 一、函数 理解函数的封装特性,掌握函数的语法规则 1.1 声明和调用 函数可以把具有相同或相似逻辑的代…...
Qt环境配置VTK
Qt与VTK的结合为开发者提供了强大的跨平台图形界面开发能力和三维可视化处理能力。本教程旨在详细介绍如何配置Qt环境以使用VTK库,从而为开发者打造高效、强大的三维可视化应用。 一、准备工作 在开始之前,确保您的开发环境中已经安装了Qt和CMake。Qt提…...

腾讯云最新活动_腾讯云促销优惠_代金券-腾讯云官网入口
腾讯云服务器多少钱一年?62元一年起,2核2G3M配置,腾讯云2核4G5M轻量应用服务器218元一年、756元3年,4核16G12M服务器32元1个月、312元一年,8核32G22M服务器115元1个月、345元3个月,腾讯云服务器网txyfwq.co…...
如何创建自己的Spring Boot Starter并为其编写单元测试
当我们想要封装一些自定义功能给别人使用的时候,创建Spring Boot Starter的形式是最好的实现方式。如果您还不会构建自己的Spring Boot Starter的话,本文将带你一起创建一个自己的Spring Boot Starter。 快速入门 创建一个新的 Maven 项目。第三方封装的…...
数据分析---常见处理逻辑
目录 数据清洗数据转换数据聚合数据筛选增删改查(以查为例)数据清洗 去除重复值:使用DISTINCT关键字去除重复行。//这将返回一个包含所有不重复城市的结果集 SELECT DISTINCT city FROM students;处理缺失值:使用IS NULL或IS NOT NULL判断是否为空值,并使用COALESCE或CASE…...
2024-02-26(金融AI行业概览与大数据生态圈)
1.最开始的风控是怎么做的? 人审 吃业务经验 不能大批量处理,效率低下 不适用于移动互联网的金融场景 2.建模的概念 建模就是构造一个数学公式,能将我们手上有的数据输入进去,通过计算得到一些预测结果。 比如初高中学习的…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...

使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...