Flutter中的事件處理


Flutter中的事件處理

無論是在Android中還是iOS中,都是有事件響應的。其主要是通過手指進行觸摸,當手指接觸到屏幕后,便開始進行事件響應了。

基本概念:指針事件

在Flutter的原始事件模型中,在手指接觸屏幕發起接觸事件時,flutter會首先確定手指與屏幕發生接觸的位置上究竟有哪些組件。然后通過命中測試(Hit Test)交給最內層的組件去響應。換句話說,也就是先從渲染樹的最底層的根的位置向上遍歷,直到遍歷到根結點位置。

flutter中的主要的事件響應分為三個部分組成 PointerDownEventPointerMoveEventPointerUpEvent 三個事件,分別是手指下落事件,手指移動事件,手指抬起事件。PointerEvent 是Flutter的原始指針事件的基礎類。主要返回有

  • position:全局坐標的偏移量
  • delta:兩次指針移動事件的距離
  • pressure:按壓力度,如果手機不支持,始終返回1
  • orientation:指針移動方向,是一個角度值

對於原始指針事件的監聽,Flutter提供了一個Listener類。這個類可以用它監聽包裹的子組件的原始指針事件。

Listener(
	onPointerDown:(downPointEvent){},
	onPointerMove:(movePointEvent){},
	onPointerUp:(upPointEvent){},
  behavior:HitTestBehavior,
	child: Widget
)

behavior是決定子組件如何響應命中測試,值類型是HitTestBehavior,是一個枚舉類型。主要的取值有

  • deferToChild:子組件一個接一個地命中測試,如果子組件中有命中測試的,那么當前組件會收到指針事件,並且父組件也會收到指針事件。
  • opaque:在進行命中測試時,當前組件會被當成不透明進行處理,單擊的響應區域即為單擊區域。
  • translucent:組件自身和底部可視區域都能夠響應命中測試,當點擊頂部組件時,頂部組件和底部組件都可以接收到指針事件。

忽略事件

兩個組件 AbsorbPointer , IgnorePointer

編號 組件名稱 組件說明
1 AbsorbPointer 其包裹的組件不能夠響應事件,但是其本身能夠響應指針事件
2 IgnorePointer 包裹的組件以及其本身都不能夠響應指針事件

手勢識別:GestureDetector

如果想從組件層監聽手勢,可以使用GestureDetector等手勢響應組件。該組件可以監聽各種觸摸的行為,常用的事件如下:

編號 事件名稱 描述
1 onTapDown 接觸屏幕時觸發
2 onTapUp 離開屏幕時觸發
3 onTap 點擊屏幕時觸發
4 onTapCancel 觸發onTapDown事件但不會觸發onTap事件
5 onDoubleTap 用戶連續兩次在同一位置快讀點擊屏幕
6 onLongPress 在相同位置與屏幕保持長時間接觸
7 onVerticalDragStart 與屏幕接觸並可能開始垂直移動
8 onVerticalDragUpdate 與屏幕接觸並沿垂直方向移動
9 onVerticalDragEnd 之前與屏幕接觸並垂直移動的指針不再與屏幕接觸
10 onHorizontalDragStart 與屏幕接觸並可能開始水平移動
11 onHorizontalDragUpdate 與屏幕接觸並已沿水平方向移動
12 onHorizontalDragEnd 之前與屏幕接觸並水平移動的指針不再與屏幕接觸

如果同時監測onTap和onDoubleTap,那么在onTap后有200ms的延遲。

GestureDetector之所以能夠識別各種手勢,是因為其內部使用了一個或者多個GestureRecognizer手勢識別器。在使用手勢識別器后,需要調用 dispose() 進行資源的釋放,否則會造成大量的資源消耗。

手勢競爭與沖突

在flutter中,引入了手勢競技場的概念,用來識別究竟是哪個手勢最終響應用戶事件。該 手勢競技場 通過綜合對比用戶觸摸屏幕的時長、位移、拖拽方向來確定最終的手勢。換句話說,如果在屏幕上拖拽一個小球,那么該小球就會通過手勢競技場進行判斷移動的方向。一般只有單一方向,垂直移動或者水平移動。

事件總線

事件總線是廣播機制的一種實現方式(廣播為跨頁面事件通信提供了有效的解決方案)。訂閱者模式中包含兩種角色:發布者和訂閱者。在Flutter中:

  • 發布者主要負責在狀態改變時通知所有的訂閱者
  • 觀察者則負責訂閱事件並對接收到的事件進行處理。

使用事件總線可以實現組件之間狀態的共享,但是對於復雜場景來說,可以使用專門的管理框架例如:redux、ScopeModel或者Provider

事件通知

如果在一個比較復雜的頁面進行數據傳遞,那么使用到 事件通知 這個機制,在子節點跨層級傳遞消息機制。在Flutter的組件樹中,每一個節點都可以發送通知,通知會沿着當前節點向上傳遞,父節點則使用NotificationListener監聽子節點傳遞的消息,這種機制稱為 通知冒泡

通知冒泡用戶觸摸事件冒泡 不太一樣,通知冒泡可以中止,用戶觸摸事件冒泡不可以中止。

自定義通知

如果需要實現自定義通知,需要實現一個類並且繼承 Notification 。在Notification類中,有一個dispatch() 可以用這個類進行分發事件通知。

冒泡通知的原理

因為通知 Notification 是通過dispatch進行觸發的,因此查看dispatch的源碼,如下:

void dispatch(BuildContext? target) {
    // The `target` may be null if the subtree the notification is supposed to be
    // dispatched in is in the process of being disposed.
    target?.visitAncestorElements(visitAncestor);
}

可以知道,其是調用了visitAncestorElements方法,從當前元素開始向上遍歷父元素。當遍歷到根元素或者遍歷回調返回false時,遍歷過程中止。該冒泡通知的原理是一套自底向上的消息傳遞機制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM