0%

【文章翻譯】The Power of the Flutter’s Transform and GestureDetector Widgets

【文章內容使用 Gemini 1.5 Pro 自動產生】

當我第一次意識到 Flutter 讓我可以完全控制螢幕上的所有内容,甚至精確到每個像素時,我立即想要超越大多數應用程式 UI 的固定和可預測的世界。我可以使用 [CustomPaint](https://api.flutter.dev/flutter/widgets/CustomPaint-class.html) 繪製的完全自訂 Widget 渴望擺脫典型的 ScrollView 或 Container。我希望能夠移動、放大和縮小,以及在 Flutter 創造的世界中導航。[Transform](https://api.flutter.dev/flutter/widgets/Transform-class.html) Widget 成為我在這個世界中導航的工具,而 [GestureDetector](https://api.flutter.dev/flutter/widgets/GestureDetector-class.html) 提供了控制項。

GestureDetector 提供了對大多數手勢的便捷存取,而 Transform 提供了修改子 Widget 被視角的能力。兩者都是簡單的獨立 Widget,遵循 Flutter 的組合模式。當我們將兩者結合在一起時,Widget 上的每個手勢都成為探索的方式。

變換簡介

儘管功能强大,但 Transform Widget 實際上只做的就是接收一個變換矩陣並將其應用於其子 Widget。這會導致子 Widget 相對於父 Widget 的平移、縮放、旋轉,甚至傾斜,所有這些都由一個簡單的 [Matrix4](https://api.flutter.dev/flutter/vector_math/Matrix4-class.html) 物件指定。

在進行變換時,矩陣非常方便使用,因為它們是可組合的。最初,儲存單獨的平移、縮放、旋轉和傾斜參數非常直观,但很容易在順序等方面造成歧义。

想象一下使用者連續執行一系列手勢。如果手勢只是一系列拖動,那麼我們可以輕鬆地將最終變換儲存為結果位置 Offset。但是,如果使用者拖動,然後在新的位置旋轉,並重複此操作幾次,我們如何跟踪最終狀態?一個 Offset 和一個弧度的倍數是不夠的,即使我們也包括一個焦點。我們必須跟踪使用者執行的操作的不断擴大的清單,並迭代整個過程才能獲得最終狀態。

一個變換矩陣可以與任意數量的其他變換矩陣無限次結合,結果始終是另一個相同大小的單一矩陣。GPU 在執行這種數學運算方面速度非常快,即使是大規模並行運算,例如針對螢幕上的每個像素。這使得它非常適合儲存類似 Transform 這樣的 Widget 的狀態,並且結果是一個非常簡單的 Widget 供 Flutter 開發人員使用。

偵測手勢

如果我們將一些使用者手勢與使用 GestureDetector 更新變換矩陣綁定在一起,那麼使用者就可以自由導航我們向他們顯示的場景。GestureDetector 提供了對拖動等手勢的便捷存取,我們可以使用它進行平移,捏合,用於縮放,甚至用於兩指旋轉。

GestureDetector 為各種手勢及其開始、更新和結束狀態提供了許多不同的回調。但是,如果您實作類似於圖中所示的演示(將幾個手勢結合在一起),那麼您只需要縮放回調。onScaleUpdate 回調提供了一個 focalPoint,水平和垂直縮放,以及旋轉,所有這些都在一個回調中。這允許您同時響應多個手勢,例如,如果使用者正在一個手勢中旋轉和縮放。請查看 [ScaleUpdateDetails](https://api.flutter.dev/flutter/gestures/ScaleUpdateDetails-class.html) 以了解 onScaleUpdate 回調中提供的所有內容。

在這些物理變換中,另一個經常實作的功能是慣性。在使用者完成手勢後,他們可能會期望變換繼續一段時間,然後才緩慢停止。Flutter 在所有這些手勢的結束回調中提供了「速度」參數,包括縮放。正如您可能從基於物理的移動中猜測到的那樣,如果使用者快速移動手指,則此值更大;如果使用者慢速移動手指,則此值更小。

您可以使用 Flutter 的另一個强大基礎設施 [Tween](https://api.flutter.dev/flutter/animation/Tween-class.html) 動畫來建立這種慣性效果。使用手勢結束時的速度和位置,以及一些基本的物理知識,您可以計算出一個最終位置和持續時間,並將其提供給 Tween,讓它處理其他所有事情。Flutter 甚至包括一個 [摩擦模擬類別](https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/physics/friction_simulation.dart) 來為您處理一些這些計算,並使事物感覺非常逼真。

結論

將 Transform 和 GestureDetector 結合起來,為我們提供了一個极其强大的工具。從移動棋盤(如螢幕截圖所示)到導航地圖,到提供互動式圖片檢視器等等,無數的功能都變得可能。

這裡顯示的應用程式目前可以在 [Flutter Gallery 應用程式](https://play.google.com/store/apps/details?id=io.flutter.demo.gallery&hl=en_US) 中作為演示使用。所有程式碼都是 Flutter 開源儲存庫的主要部分,可以在 [變換演示原始碼](https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/transformations/transformations_demo.dart) 中找到。大多數變換邏輯都在 [GestureTransformable](https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/transformations/transformations_demo_gesture_transformable.dart) 類別中,包括 [慣性動畫](https://github.com/flutter/flutter/blob/9d724d4c4483b585dfd4bfd719844802f8b38abe/examples/flutter_gallery/lib/demo/transformations/transformations_demo_gesture_transformable.dart#L503)。


Flutter 的 Transform 和 GestureDetector Widget 的强大功能 最初發佈在 Medium 上的 Flutter,人們在那裡透過突出顯示和回應這個故事來繼續討論。