> 文章列表 > 一个实现跳转到更多页面的黏性交互的通用组件

一个实现跳转到更多页面的黏性交互的通用组件

一个实现跳转到更多页面的黏性交互的通用组件

 一个实现跳转到更多页面的黏性交互的通用组件

本文字数:3344

预计阅读时间:9分钟

背景和现状

随着移动互联网的快速发展,通信费用大幅降低,信息爆炸,应用软件展示的信息越来越来,为了有效地组织和展示信息,各大移动平台都提供了列表滚动组件方便开发者使用。 RecyclerView 是  Android 平台使用频率很高的列表滑动组件,它简单易用且能够实现复杂多样的效果,同时既支持竖向滑动又支持横向滑动。

在实际开发中, RecyclerView 中的内容横向向左滑动到 RecyclerView 的最右边后需要让用户看到更多信息是很常见的需求,为了实现此需求,需要通过交互形式提示用户进行操作跳转到更多内容展示页。传统的技术方案是在 RecyclerView 末尾添加一个 item view 用来提示用户点击跳转,这种技术方案有如下的缺点:

  1. 增加了开发工作量,每个需要实现跳转需求的 RecyclerView 都需要增加一个多余的 item view ;

  2.  RecyclerView向左滑动到最右边后,需要用户二次操作,手动点击才能实现跳转;

  3. 这种交互方式很生硬,让用户觉得很无趣,降低了更多页面的曝光率;

全新的技术方案

本技术方案能完美解决传统技术方案的缺点,实现了一个通用组件 HorStickyNavLayout ,采用全新的、更加人性化的交互流程。将有更多跳转需求的 RecyclerView 作为 HorStickyNavLayout 的子 view 即可,没有多余的开发工作量;RecyclerView 横向向左滑动到最右边后,继续滑动有黏性跟手效果,同时逐渐露出根据滚动距离变换的提示文案,整个交互过程顺滑有趣,松手后直接实现跳转,提高了页面跳转的转化率。而且,本技术方案还兼容处理了fling惯性滑动,更加的流畅,提升了用户的使用体验。

原理简述

本技术方案提供了一个承载RecyclerView的父ViewGroup HorStickyNavLayout,RecyclerView大小和 HorStickyNavLayout 一致, HorStickyNavLayout 中额外添加一个 FooterView 去负责绘制提示文案,初始状态, FooterView 放在 HorStickyNavLayout 的最右边外侧,即 FooterView 不在可见区域内。当 RecyclerView 向左滑动到最右边后,继续滑动的时候,将 HorStickyNavLayout 内容整体向左滚动,这样 FooterView 就会进入可见区域,同时在 FooterView 的可见区域内绘制提示文案,根据滚动距离来显示不同的提示文案,若滚动距离小于(等于)阈值(MAX_WIDTH)绘制“继续滑动”,若滚动距离大于阈值绘制“发现更多”。需要说明的是,如果是 fling 惯性滑动(手指离开屏幕时,view 还会进行一个继续滑行的动作,称之为 fling )导致 RecyclerView 向左滑到了最右边,让惯性滑动将 HorStickyNavLayout 内容整体向左最多滚动 MAX_WIDTH 距离,目的是保持在“继续滑动”完全露出的状态即可,符合用户日常交互习惯。滑动结束,若 HorStickyNavLayout 内容滚动距离小于阈值 MAX_WIDTH ,通过动画继续向左滚动,让“继续滑动”提示文案完全露出,若滚动距离大于阈值,通过动画回弹(向右滚动),直到保持在“继续滑动”完全露出的状态。

技术方案的详细阐述

HorStickyNavLayout组件实现原理

  • 首先讲一下 HorStickyNavLayout 组件的结构: HorStickyNavLayout 继承自 FrameLayout, HorStickyNavLayout 被 inflate 之后(onFinishInflate 回调时机),此时就只有一个子 view RecyclerView ,将 RecyclerView 存储在 mChildView 变量中以供在测量阶段使用,然后将 FooterView (后面会讲到)添加到 HorStickyNavLayout 里。在测量(measure)阶段,将 RecyclerView 的测量高度存储在 mHeight 变量中以供在布局阶段使用。在布局(layout)阶段,将 FooterView 放在 orStickyNavLayout 最右外侧。

  • 接着讲一下 HorStickyNavLayout 的核心功能实现:orStickyNavLayout 实现了 NestedScrollingParent2 接口,通过这个接口和 RecyclerView (实现了 NestedScrollingChild2 接口)配合实现嵌套滑动。 RecyclerView 作为 HorStickNavLayout 的子 view , RecyclerView 开始滑动的时候,会通过 onStartNestedScroll 方法通知 HorStickNavLayout 嵌套滑动开始了,在这个时机 HorStickNavLayout 可以做一些初始化的工作,紧接着 RecyclerView 会通过 onNestedPreScroll 方法把 recyclerView (target)、滑动距离(dx 、 dy)和引起滑动类型(type)信息通知给 HorStickNavLayout , HorStickNavLayout 根据这些信息分情况进行处理:

    一个实现跳转到更多页面的黏性交互的通用组件

  1. RecylerView 向左滑到了最右边且是向左滑动(dx大于等于0)时,提示文案逐渐露出(图1),进一步分情况处理:

  • 如果 HorStickNavLayout 当前的滚动距离 scrollX 小于阈值,说明提示文案还没有完全露出,那么让 HorStickNavLayout 内容最多滚动不超过阈值的距离,保证提示文案“继续滑动”处于完全露出状态即可(图2),符合用户的交互习惯;

  • 如果 HorStickNavLayout 当前的滚动距离 scrollX 大于阈值,为了实现黏性效果,让 HorStickNavLayout 的内容可以继续滚动,滚动距离最多不超过3倍阈值(图3);

  • 如果是 fling 惯性引起的滑动,由于惯性的原因, onNestedPreScroll 会被回调很多次,为了优化用户体验,分情况处理:

  • 如果是手指触摸导致的滑动,将滑动距离dx换算成 HorStickNavLayout 内容(其实就是子 viewRecyclerView 和 FooterView )需要滚动的偏移距离 by ,调用 scrollBy 方法执行滚动,同时把滚动距离 scrollX 传给 FooterView 绘制提示文案(图1);

RecylerView 向左滑到了最右边且是向右滑动(dx小于0)时,此时 HorStickNavLayout 内容向左滚动了有一段距离,即 scrollX 是大于0的,那么让 HorStickNavLayout 中的内容向右滚动,提示文案逐渐消失,最多滚动到 scrollX 等于0,然后,无论是触摸引起的还是 fling 引起的多余滑动距离, HorStickNavLayout 不再处理,交由 RecyclerView 继续处理,这样实现了嵌套滑动的连贯性。源码如下:

一个实现跳转到更多页面的黏性交互的通用组件

滑动停止时,RecyclerView通过onStopNestedScroll方法通知 HorStickNavLayout ,HorStickNavLayout根据当前的滚动距离 scrollX分情况处理:

一个实现跳转到更多页面的黏性交互的通用组件

  1. 如果滚动距离 scrollX 大于阈值,那么执行 OffSetListener 接口的 onFinish 方法回调给外部,实现跳转逻辑,并且执行 ProgressAnimation 动画,将滚动距离回弹到完全展示“继续滑动”提示文案状态(图2);

  2. 如果滚动距离  scrollX 小于阈值(图1),执行 UnfoldAnimation 动画,让 HorStickNavLayout 内容滚动到完全展示“继续滑动”提示文案状态(图2);源码如下:

    一个实现跳转到更多页面的黏性交互的通用组件

FooterView的原理:

FooterView是用来绘制提示文案的组件,FooterView根据 HorStickNavLayout 内容的滚动距离 scrollX 将 canvas 向右平移,然后将提示文案逐个在 canvas X 轴负方向上绘制,并且 x 值保持不变,这样可以实现,随着滚动距离 scrollX 从小到大,提示文案是逐渐露出并且是固定在最右边的效果。

至此,本技术方案使用到的原理及步骤介绍完毕。

一个实现跳转到更多页面的黏性交互的通用组件

图1
一个实现跳转到更多页面的黏性交互的通用组件
图2
一个实现跳转到更多页面的黏性交互的通用组件
图3