返回

自定义View事件篇进阶篇(二)-自定义NestedScrolling实战

Android

嵌套滑动机制:全面解读 NestedScrolling 的实战应用

什么是嵌套滑动?

当父容器和子视图同时响应滑动操作时,就会发生嵌套滑动。例如,在一个包含可滚动列表的 CoordinatorLayout 中,当用户向上滑动列表时,如果列表滑动距离太小,CoordinatorLayout 就会消耗掉这次滑动事件,而列表不会响应;但如果列表滑动距离较大,CoordinatorLayout 就会把这次滑动事件传递给列表。

NestedScrolling 机制

为了解决嵌套滑动带来的冲突,谷歌推出了 NestedScrolling 机制。该机制通过定义一组接口,允许父容器和子视图之间进行通信,协商谁来处理滑动事件。

NestedScrollingParent

NestedScrollingParent 接口代表父容器,它定义了一组方法,用于处理与嵌套滑动相关的事件。这些方法包括:

  • onStartNestedScroll:当子视图开始嵌套滑动时调用
  • onNestedScrollAccepted:当父容器接受子视图的嵌套滑动时调用
  • onStopNestedScroll:当嵌套滑动停止时调用
  • onNestedScroll:当子视图滚动时调用,传递已消耗的滑动距离和未消耗的滑动距离
  • onNestedFling:当子视图发生惯性滑动时调用
  • onNestedPreScroll:在父容器进行滚动之前调用,允许子视图预先消耗滑动距离

NestedScrollingChild

NestedScrollingChild 接口代表子视图,它也定义了一组方法,用于处理与嵌套滑动相关的事件。这些方法包括:

  • isNestedScrollingEnabled:指示子视图是否启用嵌套滑动
  • setNestedScrollingEnabled:设置子视图是否启用嵌套滑动
  • startNestedScroll:启动嵌套滑动,指定滑动方向
  • stopNestedScroll:停止嵌套滑动
  • dispatchNestedScroll:分发嵌套滑动事件,传递已消耗的滑动距离和未消耗的滑动距离
  • dispatchNestedPreScroll:分发嵌套预滑动事件,允许父容器预先消耗滑动距离
  • dispatchNestedFling:分发嵌套惯性滑动事件

实战应用

要实现嵌套滑动效果,需要在父容器和子视图中分别实现 NestedScrollingParent 和 NestedScrollingChild 接口。以下是具体步骤:

  1. 定义父容器和子视图 :创建继承自 NestedScrollingParent 和 NestedScrollingChild 的类。
  2. 实现接口方法 :在父容器类中实现 onStartNestedScroll、onNestedScrollAccepted 等方法,在子视图类中实现 isNestedScrollingEnabled、startNestedScroll 等方法。
  3. 布局关联 :在布局文件中,将父容器和子视图关联起来,并设置嵌套滑动属性。

解决滑动冲突

为了解决滑动冲突,可以通过以下方法:

  • 设置 NestedScrollingParent 的 nestedScrollAxes 属性,指定父容器响应的滑动方向。
  • 设置 NestedScrollingChild 的 nestedScrollingEnabled 属性,启用或禁用子视图的嵌套滑动功能。
  • 在 NestedScrollingParent 和 NestedScrollingChild 中重写 dispatchNestedScroll、dispatchNestedPreScroll 和 dispatchNestedFling 方法,控制滑动事件的传递。

使用 NestedScrollingParent2 和 NestedScrollingChild2

在 Android API 29 中,引入了 NestedScrollingParent2 和 NestedScrollingChild2 接口,新增了 type 参数,指定滑动事件的类型(例如触摸、非触摸、动画等),提供了更精细的滑动控制。

常见问题解答

1. 何时使用 NestedScrolling?
答:当需要在父容器和子视图之间协调滑动事件时,使用 NestedScrolling。

2. NestedScrollingParent 和 NestedScrollingChild 如何交互?
答:通过 NestedScrollingParent 的 onStartNestedScroll 和 onNestedScrollAccepted 方法,以及 NestedScrollingChild 的 startNestedScroll 和 dispatchNestedScroll 方法进行交互。

3. 如何解决滑动冲突?
答:通过设置 NestedScrollingParent 和 NestedScrollingChild 的属性,以及重写 dispatch 方法来解决滑动冲突。

4. NestedScrollingParent2 和 NestedScrollingChild2 有什么好处?
答:提供了更精细的滑动事件控制,通过 type 参数指定滑动事件类型。

5. 如何在自定义控件中使用 NestedScrolling?
答:实现 NestedScrollingParent 或 NestedScrollingChild 接口,并重写相应的方法来处理滑动事件。