滚动分为多个阶段。输入增量通过一系列阶段进行分派,以确保每个阶段都有机会使用或响应移动。
在整个周期中,可用输入增量和已用输入增量都会在每个步骤中传递。这为每个阶段提供了响应、使用或监听滚动事件所需的完整上下文。
如图 1 所示,滚动过程遵循以下确切顺序:
- 滚动过头: 首先接收初始输入增量,这让滚动过头有机会先做出响应(例如,通过放松活跃的拉伸效果)。
- 嵌套滚动预滚动: 在 Scroll 阶段之前,有机会对输入增量做出响应。在此阶段,可能会使用一些输入增量,或者只是对其进行监控以触发界面更改,例如收起或展开应用栏。
- 转换输入增量:根据 布局方向和方向调整原始输入增量的符号,以确保自然的滚动行为。如需了解详情,请参阅转换输入增量部分。
- 滚动: 此阶段接收根据滚动容器配置调整的可用、未用输入增量。它通常使用此增量来更新自己的滚动偏移量。
- 还原为原始输入增量:将 滚动阶段的可用和已用增量还原为原始输入增量符号。
- 嵌套滚动后滚动: 此阶段在主滚动阶段完成后做出响应,接收新更新的可用和已用增量。它可以消耗任何剩余的可用输入,也可以使用刚刚消耗的内容的上下文。
- 滚动过头: 最后一个阶段会查看最终的可用和已用增量。到达此阶段的任何剩余可用输入通常用于驱动边缘效果(例如拉伸或发光),表明用户已到达可滚动区域的边界。
转换输入增量
指针输入增量需要在各个滚动阶段进行符号调整,以匹配预期合同。在增量到达 Scroll 阶段之前,滚动修饰符会根据屏幕方向、布局方向和 RTL 上下文调整输入增量。之所以会发生这种情况,是因为原始输入会跟踪指针在屏幕上的物理像素移动(例如,向下移动会增加屏幕的 Y 坐标,从而产生正增量)。但是,为了实现“自然滚动”(即内容随手指移动),向下拖动意味着视口必须在内容上向上移动,这对应于负滚动偏移量。
来自其他输入源(例如鼠标滚轮或触控板)的输入增量在整个滚动阶段都不会转换。
示例:指针使用 Modifier.horizontalScroll() 向右移动
如需了解增量的使用和转换方式,请参阅图 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 为负数) | 不适用 | 不适用 |