大家好,我是堅果,
今天是Flutter系列第七節。今天給大家介紹flutter手勢
Flutter的安裝與設定(第一節)
35分鐘教你學會dart(第二節)
每個 Flutter 開發人員都應該知道的 16 個 Dart 技巧和竅門(第三節)
flutter架構(第四節)
如何在flutter中建構響應式布局(第五節)
flutter的版本控制工具fvm(第六節)
Flutter 提供了一些非常棒的開箱即用的小部件,它們預先建構用于處理觸摸事件,例如 in<code>InkWell</code>和<code>InkResponse</code>。這些小部件包裝您的小部件,以便它們能夠響應觸摸事件。除了這樣做之外,它還會将 Material Ink 飛濺添加到您的小部件中。<code>InkResponse</code>例如,當飛濺超出小部件的邊界時,它具有控制形狀和剪裁的選項。一個有趣的一點要注意的是<code>InkWell</code>,并<code>InkResponse</code>沒有做任何渲染,而不是他們更新父材料部件。一個常見的例子是圖像。如果将圖像包裹在 中<code>inkWell</code>,您會注意到波紋不可見。這是因為它是在Material上的圖像後面繪制的。為了使<code>Ink</code>飛濺可見,使用<code>Ink.Image</code>. 雖然對大多數任務很有用,但如果您想捕獲更多事件,例如當使用者在螢幕上拖動時,應使用<code>GestureDetector</code>.
那麼什麼是手勢檢測?它是如何工作的?
手勢檢測的基本概述是一個無狀态小部件,它在其構造函數中具有用于不同觸摸事件的參數。值得注意的是,您不能将<code>Pan</code>and<code>Scale</code>一起使用,因為它<code>Scale</code>是<code>Pan</code>. <code>GestureDetector</code>僅用于檢測手勢,是以不提供任何視覺響應(不存在Material Ink傳播)。
<code>GestureDetector</code>根據哪些回調是非空的,決定嘗試識别哪些手勢。這很有用,因為如果您需要禁用手勢,您将傳遞*null*。
讓我們以<code>**onTap**</code>手勢為例,确定<code>**GestureDetector**</code>.
首先,我們建立一個帶有<code>onTap</code>回調的 GestureDetector ,因為它是非空的,<code>GestureDetector</code>當點選事件發生時将使用我們的回調。在 内部<code>GestureDetector</code>,建立了一個手勢工廠。<code>Gesture Recognizer</code>努力确定正在處理的手勢。對于所有提供的不同回調,此過程都是相同的<code>GestureDetector</code>。在<code>GestureFactories</code>随後被傳遞到<code>RawGestureDetector</code>。
<code>RawGestureDetector</code>做檢測手勢的艱苦工作。它是一個有狀态的小部件,它在狀态改變時同步所有手勢,處理識别器,擷取所有發生的指針事件并将其發送到注冊的識别器。然後他們在Gesture Arena 中展開決鬥。
<code>RawGestureDetector</code>build 方法由 a 組成,<code>Listener</code>它是偵聽指針事件的基類。如果您想使用來自平台的原始輸入,如上升、下降或取消事件,這是您的首選課程。<code>Listener</code>不給你任何的手勢,隻是基本的<code>onPointerDown</code>,<code>onPointerUp</code>,<code>onPointerMove</code>和<code>onPointerCancel</code>事件。一切都必須手動處理,包括向Gesture Arena報告自己。如果您不這樣做,那麼您不會被自動取消,也無法參與那裡發生的互動。這是小部件方面的最低級别。
<code>Listener</code>是一個<code>SingleChildRenderObjectWidget</code>由<code>RenderPointerListener</code>extends類組成的類,這<code>RenderProxyBoxWithHitTestBehavior</code>意味着它在允許<code>HitTestBehavior</code>自定義的同時模仿其子項的屬性。
<code>HitTestBehaviour</code>有 3 個選項<code>deferToChild</code>,<code>opaque</code>和<code>translucent</code>。這些來自并配置在<code>GestureDetector</code>. <code>DeferToChild</code>預設行為。<code>Opaque</code>阻止在背景的小部件接收事件并<code>Translucent</code>允許背景小部件接收事件。
那麼如果您希望父級和子級都接收指針事件呢?
讓我們想象一下您有一個嵌套清單并且想要同時滾動這兩個清單的情況。為此,您需要父級和子級都接收該指針。您将命中測試行為配置為半透明,確定兩個小部件都接收事件,但事情沒有按計劃進行……這是為什麼?
那麼,上述問題的答案是<code>GestureArena</code>。
<code>GestureArena</code>用于手勢消歧。所有識别器都被發送到這裡,他們在那裡進行了戰鬥。在螢幕上的任何給定點,都可以有多個手勢識别器。Arena 考慮了使用者觸摸螢幕的時間長度、傾斜度以及使用者拖動的方向來确定獲勝者。
父清單和子清單都将它們的識别器發送到競技場,但(在撰寫本文時)隻有一個會獲勝,而且總是碰巧是子清單。
解決方法是将 a<code>RawGestureDetector</code>與您自己的<code>GestureFactory</code>'s一起使用,這會改變競技場的表現方式。
例如,讓我們建立一個由兩個容器組成的簡單應用程式。目标是讓孩子和父母都收到手勢。
兩者都将被包裹在一個<code>RawGestureDetector</code>. 接下來,我們将建立一個自定義手勢識别器,<code>AllowMultipleGestureRecognizer</code>. <code>GestureRecognizer</code>是所有其他識别器從其繼承的基類。它為類提供了基本的 API,以便它們能夠與手勢識别器一起工作/互動。值得注意的是,<code>GestureRecognizer</code>它并不關心識别器本身的具體細節。
在上面的代碼中,我們建立了一個<code>AllowMultipleGestureRecognizer</code>擴充<code>TapGestureRecognizer</code>. 這意味着它能夠繼承<code>TapGestureRecognizer</code>. 在這個例子中,我們覆寫<code>rejectGesture</code>這樣的,而不是處理識别器,它被手動接受。
現在我們将我們的自定義手勢識别器傳遞<code>GestureRecognizerFactoryWithHandlers</code>給<code>RawGestureDetector</code>.
現在我們将我們的自定義手勢識别器傳遞<code>GestureRecognizerFactoryWithHandlers</code>給<code>RawGestureDetector</code>. 該工廠需要兩個屬性,一個構造函數和一個用于構造和初始化手勢識别器的初始化器。我們使用 lambda 來傳遞這些參數。如上面代碼中所述,構造函數傳回一個新執行個體,<code>AllowMultipleGestureRecognizer</code>而初始化器采用<code>instance</code>用于偵聽點選并将一些文本列印到控制台的屬性。這将對兩個容器重複,唯一的差別是列印的文本。
這是示例應用程式的完整源代碼:
那麼運作上述代碼的結果是什麼呢?
當您點選黃色容器時,兩個小部件都會收到點選,是以控制台會列印兩條語句。
該應用程式:

控制台輸出
回到我們的Tap示例,在發生這種情況後,<code>onTap</code>現在将執行映射到的函數。
總結
今天我們研究了 Flutter 架構如何處理手勢。我們首先檢視 Flutter 提供的用于處理點選和其他觸摸事件的出色的預建構小部件。接下來,我們繼續<code>GestureDetector</code>研究它的内部工作方式。通過一個例子,我們了解了 Flutter 是如何處理 Tap 手勢的。我們穿越了這片土地<code>RawGestureDetector</code>,<code>Listener</code>聆聽并欣賞了被稱為的秘密 Flutter 搏擊俱樂部的聲音<code>GestureArena</code>。
最後,我們從應用程式的角度介紹了 Flutter 中的大部分手勢系統。有了這些知識,您現在應該更好地了解螢幕上的觸摸是在幕後進行的。如果您有任何問題或疑慮,請随時和我聯系,下面是我的公衆号,
那我們下節再見!