了解滚动阶段

滚动分为多个阶段。输入增量通过一系列阶段进行分派,以确保每个阶段都有机会使用或响应移动。

在整个周期中,可用输入增量和已用输入增量都会在每个步骤中传递。这为每个阶段提供了响应、使用或监听滚动事件所需的完整上下文。

一个滚动周期图,显示用户滚动事件的滚动阶段
图 1.一个滚动周期图,显示了用户滚动事件的滚动阶段。

如图 1 所示,滚动过程遵循以下确切顺序:

  1. 滚动过头: 首先接收初始输入增量,这让滚动过头有机会先做出响应(例如,通过放松活跃的拉伸效果)。
  2. 嵌套滚动预滚动: 在 Scroll 阶段之前,有机会对输入增量做出响应。在此阶段,可能会使用一些输入增量,或者只是对其进行监控以触发界面更改,例如收起或展开应用栏。
  3. 转换输入增量:根据 布局方向和方向调整原始输入增量的符号,以确保自然的滚动行为。如需了解详情,请参阅转换输入增量部分。
  4. 滚动: 此阶段接收根据滚动容器配置调整的可用、未用输入增量。它通常使用此增量来更新自己的滚动偏移量。
  5. 还原为原始输入增量:将 滚动阶段的可用和已用增量还原为原始输入增量符号。
  6. 嵌套滚动后滚动: 此阶段在主滚动阶段完成后做出响应,接收新更新的可用和已用增量。它可以消耗任何剩余的可用输入,也可以使用刚刚消耗的内容的上下文。
  7. 滚动过头: 最后一个阶段会查看最终的可用和已用增量。到达此阶段的任何剩余可用输入通常用于驱动边缘效果(例如拉伸或发光),表明用户已到达可滚动区域的边界。

转换输入增量

指针输入增量需要在各个滚动阶段进行符号调整,以匹配预期合同。在增量到达 Scroll 阶段之前,滚动修饰符会根据屏幕方向、布局方向和 RTL 上下文调整输入增量。之所以会发生这种情况,是因为原始输入会跟踪指针在屏幕上的物理像素移动(例如,向下移动会增加屏幕的 Y 坐标,从而产生正增量)。但是,为了实现“自然滚动”(即内容随手指移动),向下拖动意味着视口必须在内容上向上移动,这对应于负滚动偏移量。

来自其他输入源(例如鼠标滚轮或触控板)的输入增量在整个滚动阶段都不会转换。

示例:指针使用 Modifier.horizontalScroll() 向右移动

图示:指针向右移动的手势
图 2.一个图表,用于映射指针向右移动的手势。

如需了解增量的使用和转换方式,请参阅图 2,该图表用于映射指针向右移动的手势。

  • 预滚动: 手势以 100 的正原始输入增量开始。
    • 滚动回弹 会观察到这一点并消耗 10 ,留下 90
    • 嵌套滚动预滚动 让父组件有机会做出响应,使用 30 。剩余的原始增量为 60
  • 转换 A:在进入 Scroll 阶段之前, horizontalScroll 会将剩余的正原始增量 (60) 反转为 负增量 (-60)。这可确保视口向左移动,以便内容看起来随用户的手指向右移动。
  • 滚动: 目标可滚动组件使用此转换后的增量的一部分来更新其滚动偏移量。在此示例中,它使用 -30,留下-30未使用。
  • 转换 B: 未使用的滚动增量 (-30) 会转换回正原始增量 (30) ,以匹配嵌套滚动和滚动回弹的合同。
  • 后滚动: 剩余的原始增量会传递回流水线。
    • 嵌套滚动后滚动 使用 10 ,留下 20
    • 滚动过头效果 使用最终的 20 来驱动视觉边缘效果(例如拉伸或发光),从而将输入增量完全解析为 0

指针输入增量转换参考

下表概述了指针输入的各个阶段和方向的输入增量符号。

原始输入增量 滚动过头效果 嵌套滚动 具有水平方向的 scrollableArea 具有水平方向的 scrollableArea(反向) 具有垂直方向的 scrollableArea 具有垂直方向的 scrollableArea(反向)
指针向上 移动 负数 负数 负数 不适用 不适用 正数 负数
指针向下 移动 正数 正数 正数 不适用 不适用 负数 正数
指针向左 移动 负数 负数 负数 正数(对于 RTL 为负数) 负数(对于 RTL 为正数) 不适用 不适用
指针向右 移动 正数 正数 正数 负数(对于 RTL 为正数) 正数(对于 RTL 为负数) 不适用 不适用