瞭解捲動階段

捲動分為多個階段。輸入差異會透過一系列階段分派,確保每個階段都有機會消耗或回應動作。

在這個週期中,可用的輸入差異和消耗的輸入差異都會在每個步驟中傳遞。這樣一來,每個階段都能取得完整背景資訊,以便回應、使用或監聽捲動事件。

捲動週期圖表,顯示使用者捲動事件的捲動階段
圖 1. 捲動週期圖,顯示使用者捲動事件的捲動階段。

如圖 1 所示,捲動程序會按照以下順序進行:

  1. 過度捲動:先接收初始輸入差異,讓過度捲動有機會先做出反應 (例如放寬主動延展效果)。
  2. 巢狀捲動預先捲動:在「捲動」階段之前,有機會對輸入差異做出反應。在這個階段,系統可能會耗用部分輸入差異,或只是監控輸入差異,以觸發 UI 變更,例如收合或展開應用程式列。
  3. 轉換輸入差異:根據版面配置方向和方向調整原始輸入差異的正負號,確保捲動行為自然。詳情請參閱「轉換輸入差異」一節。
  4. 捲動:這個階段會接收可用的未消耗輸入差異,並根據捲動容器設定進行調整。通常會使用這個差異值更新自己的捲動偏移。
  5. 還原為原始輸入差異:將捲動階段的可用和已消耗差異,還原為原始輸入差異符號。
  6. 巢狀捲動後捲動:這個階段會在主要捲動階段完成後做出反應,接收新更新的可用和已消耗差異。它可以消耗任何剩餘的可用輸入內容,或使用剛消耗內容的脈絡。
  7. 過度捲動:最後一個階段會查看最終可用和已消耗的差異。任何剩餘的可用輸入內容,通常會用於驅動邊緣效果,例如拉伸或發光,表示使用者已達到可捲動區域的邊界。

轉換輸入差異

指標輸入差異需要調整捲動階段的正負號,才能符合預期合約。在差異值達到「捲動」階段之前,捲動修飾符會根據方向、版面配置方向和 RTL 情境調整輸入差異值。這是因為原始輸入會追蹤指標在螢幕上的實體像素移動 (例如向下移動會增加螢幕的 Y 座標,產生正差異)。不過,如要達到「自然捲動」效果,讓內容隨著手指移動,向下拖曳代表可視區域必須向上移動,這對應到負捲動偏移。

滑鼠滾輪或觸控板等其他輸入來源的輸入差異,在捲動階段不會轉換。

範例:使用 Modifier.horizontalScroll() 將指標向右移動

圖表:指標向右移動的手勢
圖 2. 圖表,顯示指標向右移動的手勢。

如要瞭解如何使用及轉換差異,請參閱圖 2,其中對應了指標向右移動的手勢。

  • 捲動前:手勢會以正原始輸入差異 100 開始。
    • 過度捲動會觀察到這項操作並消耗 10,剩下 90。
    • 巢狀捲動預先捲動可讓父項元件有機會做出反應,消耗 30。剩餘的原始差異為 60。
  • 轉換 A:進入捲動階段前,horizontalScroll 會將剩餘的正原始差異 (60) 反轉為負差異 (-60)。這樣一來,可確保可視區域向左移動,讓內容看起來隨著使用者的手指往右移動。
  • 捲動:目標可捲動元件會耗用部分轉換後的差異,更新捲動偏移。在本例中,它會消耗 -30,剩下 -30 未消耗。
  • 轉換 B:未消耗的捲動差異 (-30) 會轉換回正原始差異 (30),以符合巢狀捲動和過度捲動的合約。
  • 捲動後:剩餘的原始差異會傳回管道。
    • 巢狀捲動後捲動會消耗 10,剩下 20。
    • 過度捲動效果會使用最後的 20 像素來驅動視覺邊緣效果,例如拉伸或發光,將輸入差異完全解析為 0。

指標輸入差異轉換參考資料

下表概述輸入差異在不同階段和指標輸入方向的簽署方式。

原始輸入差異 過度捲動效果 巢狀捲動 scrollableArea (橫向) scrollableArea,橫向 (反向) 直向 scrollableArea scrollableArea,直向 (反向)
游標向上移動 負面 負面 負面 不適用 不適用 正面 負面
游標向下移動 正面 正面 正面 不適用 不適用 負面 正面
游標向左移動 負面 負面 負面 正值 (由右至左為負值) 負值 (RTL 為正值) 不適用 不適用
游標向右移動 正面 正面 正面 負值 (RTL 為正值) 正值 (由右至左為負值) 不適用 不適用