当前位置: 首页 > news >正文

Android进阶之路 - RecyclerView停止滑动后Item自动居中(SnapHelper辅助类)

之前一直没注意 SnapHelper 辅助类的功能,去年的时候看到项目中仅通过俩行代码设置 RecyclerView 后就提升了用户体验,觉得还是很有必要了解一下,尝试过后才发现其 PagerSnapHelperLinearSnapHelper 子类可以作用于不同场景,且听吾言

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
      • 使用方式

你在开发项目中遇到过这样的场景吗?

HintRecyclerView 为水平滑动 && 子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 支持定位移动后的数据(视图)角标
  • FlingListenerScrollListener 滑动监听&滑动速度监听

在这里插入图片描述

PagerSnapHelperLinearSnapHelper 除基类方法外,支持获取居中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>
http://www.lryc.cn/news/307927.html

相关文章:

  • 高性能图表组件LightningChart .NET v11.0发布——增强DPI感知能力
  • 神经网络系列---计算图基本原理
  • 3D数字孪生
  • C++惯用法之空基类优化
  • 【生成式AI】ChatGPT 原理解析(2/3)- 预训练 Pre-train
  • Day03:Web架构OSS存储负载均衡CDN加速反向代理WAF防护
  • C++多线程同步(上)
  • 猜猜心里数字(个人学习笔记黑马学习)
  • 实用Pycharm插件
  • 数据结构试题练习
  • s-table和columns初始化不完整,造成table文件的filter报错
  • SLA 是什么?如何实现 SLA 管理
  • 火灾安全护航:火灾监测报警摄像机助力建筑安全
  • JavaScript 基础学习笔记(五):函数、作用域、匿名函数
  • Qt环境配置VTK
  • 腾讯云最新活动_腾讯云促销优惠_代金券-腾讯云官网入口
  • 如何创建自己的Spring Boot Starter并为其编写单元测试
  • 数据分析---常见处理逻辑
  • 2024-02-26(金融AI行业概览与大数据生态圈)
  • git忽略某些文件(夹)更改说明
  • python爬虫实战:获取电子邮件和联系人信息
  • post请求同时上传文件并传递其他参数的前后端写法
  • 【数仓】基本概念、知识普及、核心技术
  • ky10-server docker 离线安装包、离线安装
  • Linux的gdb调试
  • IO多路复用-select模型
  • 班级事务管理系统设计与实现
  • 金三银四面试必问:Redis真的是单线程吗?
  • notejs+nvm+angular+typescript.js环境 Hertzbeat 配置
  • docker安装单机版canal和使用