Flutter_點(diǎn)擊事件和手勢
Flutter中的手勢系統(tǒng)有兩個(gè)獨(dú)立的層扒秸。第一層具有原始指針事件骚露,其描述屏幕上指針(例如蕴掏,觸摸障般,鼠標(biāo)和測針)的位置和移動(dòng)。第二層具有手勢盛杰,其描述由一個(gè)或多個(gè)指針移動(dòng)組成的語義動(dòng)作挽荡。
指針
指針表示用戶與設(shè)備屏幕交互的原始數(shù)據(jù)。有四種類型的指針事件:
- PointerDownEvent 指針已在特定位置與屏幕聯(lián)系即供。
- PointerMoveEvent 指針已從屏幕上的一個(gè)位置移動(dòng)到另一個(gè)位置徐伐。
- PointerUpEvent 指針已停止接觸屏幕。
- PointerCancelEvent 來自此指針的輸入不再指向此應(yīng)用募狂。
代碼
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return Listener(
onPointerDown: (down) {
print("onPointerDownEvent");
},
onPointerMove: (move) {
print("onPointerMove");
},
onPointerUp: (up) {
print("onPointerUp");
},
onPointerHover: (hover) {
print("onPointerHover");
},
onPointerExit: (exit) {
print("onPointerExit");
},
onPointerCancel: (cancle){
print("onPointerCancel");
},
onPointerEnter: (enter) {
print("onPointerEnter");
},
child: Center(
child: Text(
"test",
textDirection: TextDirection.ltr,
),
),
);
}
}
在指針向下時(shí)办素,框架會對您的應(yīng)用程序執(zhí)行命中測試角雷,以確定指針與屏幕接觸的位置存在哪個(gè)小部件。然后將指針向下事件(以及該指針的后續(xù)事件)調(diào)度到命中測試找到的最內(nèi)部窗口小部件性穿。從那里勺三,事件在樹上冒泡,并被分派到從最里面的小部件到樹的根的路徑上的所有小部件需曾。沒有用于取消或停止指針事件進(jìn)一步調(diào)度的機(jī)制吗坚。
要直接從窗口小部件圖層偵聽指針事件,請使用 <b>Listener</b> 窗口小部件呆万。但是商源,通常,請考慮使用手勢(如下所述)谋减。
Listener監(jiān)聽屬性
behavior → HitTestBehavior
在命中測試期間如何表現(xiàn)牡彻。
onPointerCancel → PointerCancelEventListener
當(dāng)觸發(fā)onPointerDown的指針的輸入不再指向此接收器時(shí)調(diào)用。
onPointerDown → PointerDownEventListener
當(dāng)指針與屏幕(用于觸摸指針)接觸時(shí)調(diào)用出爹,或者在此窗口小部件的位置按下其按鈕(用于鼠標(biāo)指針)庄吼。
onPointerEnter → PointerEnterEventListener
當(dāng)指針進(jìn)入此窗口小部件的區(qū)域時(shí)調(diào)用。
onPointerExit → PointerExitEventListener
當(dāng)指針離開此窗口小部件的區(qū)域時(shí)調(diào)用严就。
onPointerHover → PointerHoverEventListener
當(dāng)未觸發(fā)onPointerDown的指針改變位置時(shí)調(diào)用总寻。
onPointerMove → PointerMoveEventListener
當(dāng)觸發(fā)onPointerDown的指針改變位置時(shí)調(diào)用。
onPointerUp → PointerUpEventListener
當(dāng)觸發(fā)onPointerDown的指針不再與屏幕接觸時(shí)調(diào)用梢为。
手勢
手勢表示從多個(gè)單獨(dú)指針事件識別的語義動(dòng)作(例如渐行,點(diǎn)擊,拖動(dòng)和縮放)铸董,甚至可能是多個(gè)單獨(dú)的指針祟印。手勢可以分派多個(gè)事件,對應(yīng)于手勢的生命周期(例如袒炉,拖動(dòng)開始,拖動(dòng)更新和拖動(dòng)結(jié)束):
-
點(diǎn)擊
- onTapDown 可能導(dǎo)致點(diǎn)擊的指針已在特定位置與屏幕聯(lián)系樊零。
- onTapUp 將觸發(fā)敲擊的指針已停止在特定位置接觸屏幕我磁。
- onTap 已經(jīng)發(fā)生了敲擊。
- onTapCancel之前觸發(fā)的指針onTapDown不會導(dǎo)致點(diǎn)擊驻襟。
-
雙擊
- onDoubleTap 用戶快速連續(xù)兩次在同一位置點(diǎn)擊屏幕夺艰。
-
長按
- onLongPress 指針長時(shí)間保持與相同位置的屏幕接觸。
-
垂直拖動(dòng)
- onVerticalDragStart 指針已接觸屏幕沉衣,可能會開始垂直移動(dòng)郁副。
- onVerticalDragUpdate 與屏幕接觸并垂直移動(dòng)的指針在垂直方向上移動(dòng)。
onVerticalDragEnd 之前與屏幕接觸并垂直移動(dòng)的指針不再與屏幕接觸豌习,并且在停止接觸屏幕時(shí)以特定速度移動(dòng)存谎。
-
水平拖動(dòng)
- onHorizontalDragStart 指針已接觸屏幕拔疚,可能開始水平移動(dòng)。
- onHorizontalDragUpdate 與屏幕接觸并水平移動(dòng)的指針在水平方向上移動(dòng)既荚。
- onHorizontalDragEnd 先前與屏幕接觸并且水平移動(dòng)的指針不再與屏幕接觸稚失,并且當(dāng)它停止接觸屏幕時(shí)以特定速度移動(dòng)。
泛 - onPanStart指針已接觸屏幕恰聘,可能開始水平或垂直移動(dòng)句各。如果 - onHorizontalDragStart或onVerticalDragStart設(shè)置了此回調(diào),則會導(dǎo)致崩潰 晴叨。
- onPanUpdate指針與屏幕接觸并沿垂直或水平方向移動(dòng)凿宾。如果 - onHorizontalDragUpdate或onVerticalDragUpdate設(shè)置了此回調(diào),則會導(dǎo)致崩潰 兼蕊。
- onPanEnd之前與屏幕接觸的指針不再與屏幕接觸初厚,并且在停止接觸屏幕時(shí)以特定速度移動(dòng)。如果onHorizontalDragEnd或 - onVerticalDragEnd設(shè)置了此回調(diào)遍略,則會導(dǎo)致崩潰 惧所。
要從小部件圖層中聆聽手勢,請使用 <b>GestureDetector</b>绪杏。
代碼
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print("onPointerDownEvent");
},
onDoubleTap: () {
print("onDoubleTap");
},
onForcePressEnd: (end) {
print("onForcePressEnd");
},
onForcePressPeak: (peak) {
print("onForcePressPeak");
},
onForcePressStart: (start) {
print("onForcePressStart");
},
onForcePressUpdate: (update) {
print("onForcePressUpdate");
},
onHorizontalDragCancel: () {
print("onHorizontalDragCancel");
},
onHorizontalDragDown: (down) {
print("onHorizontalDragDown");
},
onHorizontalDragEnd: (end) {
print("onHorizontalDragEnd");
},
onHorizontalDragStart: (start) {
print("onHorizontalDragStart");
},
onHorizontalDragUpdate: (update) {
print("onHorizontalDragUpdate");
},
onLongPressDragStart: (start) {
print("onLongPressDragStart");
},
onLongPressDragUp: (up) {
print("onLongPressDragUp");
},
onLongPressDragUpdate: (update) {
print("onLongPressDragUpdate");
},
//監(jiān)聽更多方法可以在這里添加
child: Center(
child: Text(
"test",
textDirection: TextDirection.ltr,
),
),
);
}
}
GestureDetector監(jiān)聽屬性
behavior → HitTestBehavior
在命中測試期間下愈,此手勢檢測器應(yīng)如何表現(xiàn)
child → Widget
樹中此小部件下方的小部件。
dragStartBehavior → DragStartBehavior
確定處理拖動(dòng)開始行為的方式蕾久。
excludeFromSemantics → bool
是否從語義樹中排除這些手勢势似。例如,用于顯示工具提示的長按手勢被排除僧著,因?yàn)楣ぞ咛崾颈旧碇苯影谡Z義樹中履因,因此具有顯示它的手勢將導(dǎo)致信息的重復(fù)。
onDoubleTap → GestureTapCallback
用戶快速連續(xù)兩次在同一位置點(diǎn)擊屏幕盹愚。
onForcePressEnd → GestureForcePressEndCallback
指針不再與屏幕接觸栅迄。
onForcePressPeak → GestureForcePressPeakCallback
指針與屏幕接觸并以最大力按下。力量至少是 ForcePressGestureRecognizer.peakPressure皆怕。
onForcePressStart → GestureForcePressStartCallback
指針與屏幕接觸毅舆,并用足夠的力按壓以啟動(dòng)壓力。力量至少是 ForcePressGestureRecognizer.startPressure愈腾。
onForcePressUpdate → GestureForcePressUpdateCallback
指針與屏幕接觸憋活,之前已經(jīng)通過了 ForcePressGestureRecognizer.startPressure,并且要么在屏幕的平面上移動(dòng)虱黄,要么用不同的力按壓屏幕悦即,要么同時(shí)按兩個(gè)屏幕。
onHorizontalDragCancel → GestureDragCancelCallback
先前觸發(fā)onHorizo??ntalDragDown的指針未完成。
onHorizontalDragDown → GestureDragDownCallback
指針已接觸屏幕辜梳,可能開始水平移動(dòng)粱甫。
onHorizontalDragEnd → GestureDragEndCallback
前與屏幕接觸并且水平移動(dòng)的指針不再與屏幕接觸,并且當(dāng)它停止接觸屏幕時(shí)以特定速度移動(dòng)冗美。
onHorizontalDragStart → GestureDragStartCallback
指針已接觸屏幕并開始水平移動(dòng)魔种。
onHorizontalDragUpdate → GestureDragUpdateCallback
與屏幕接觸并水平移動(dòng)的指針在水平方向上移動(dòng)。
onLongPress → GestureLongPressCallback
指針長時(shí)間保持與相同位置的屏幕接觸粉洼。
onLongPressDragStart → GestureLongPressDragStartCallback
指針長時(shí)間保持與相同位置的屏幕接觸节预。
onLongPressDragUp → GestureLongPressDragUpCallback
無論長按后是否拖動(dòng)指針,觸發(fā)長按的指針都停止接觸屏幕属韧。
onLongPressDragUpdate → GestureLongPressDragUpdateCallback
長按后安拟,指針已被拖動(dòng)。
onLongPressUp → GestureLongPressUpCallback
觸發(fā)長按的指針已停止接觸屏幕宵喂。
onPanCancel → GestureDragCancelCallback
先前觸發(fā)onPanDown的指針未完成糠赦。
onPanDown → GestureDragDownCallback
指針已接觸屏幕并可能開始移動(dòng)。
onPanEnd → GestureDragEndCallback
先前與屏幕接觸并移動(dòng)的指針不再與屏幕接觸锅棕,并且當(dāng)它停止接觸屏幕時(shí)以特定速度移動(dòng)拙泽。
onPanStart → GestureDragStartCallback
指針已經(jīng)接觸屏幕并開始移動(dòng)。
onPanUpdate → GestureDragUpdateCallback
與屏幕接觸并移動(dòng)的指針再次移動(dòng)裸燎。
onScaleEnd → GestureScaleEndCallback
指針不再與屏幕接觸顾瞻。
onScaleStart → GestureScaleStartCallback
與屏幕接觸的指針已建立焦點(diǎn),初始比例為1.0德绿。
onScaleUpdate → GestureScaleUpdateCallback
與屏幕接觸的指針表示新的焦點(diǎn)和/或比例荷荤。
onTap → GestureTapCallback
已經(jīng)發(fā)生了敲擊
onTapCancel → GestureTapCancelCallback
先前觸發(fā)onTapDown的指針不會導(dǎo)致點(diǎn)擊。
onTapDown → GestureTapDownCallback
可能導(dǎo)致點(diǎn)擊的指針已在特定位置與屏幕聯(lián)系移稳。
onTapUp → GestureTapUpCallback
將觸發(fā)敲擊的指針已停止在特定位置接觸屏幕蕴纳。
onVerticalDragCancel → GestureDragCancelCallback
先前觸發(fā)onVerticalDragDown的指針未完成。
onVerticalDragDown → GestureDragDownCallback
指針已接觸屏幕个粱,可能會開始垂直移動(dòng)古毛。
onVerticalDragEnd → GestureDragEndCallback
之前與屏幕接觸并垂直移動(dòng)的指針不再與屏幕接觸,并且在停止接觸屏幕時(shí)以特定速度移動(dòng)都许。
onVerticalDragStart → GestureDragStartCallback
指針已接觸屏幕并已開始垂直移動(dòng)稻薇。
onVerticalDragUpdate → GestureDragUpdateCallback
與屏幕接觸并垂直移動(dòng)的指針在垂直方向上移動(dòng)。
如果您正在使用Material Components梭稚,那么這些小部件中的許多小部件已經(jīng)響應(yīng)了輕擊或手勢颖低。例如絮吵, IconButton和 FlatButton 響應(yīng)按下(輕擊)弧烤,并 ListView 響應(yīng)滑動(dòng)以觸發(fā)滾動(dòng)。如果您沒有使用這些小部件,但想要點(diǎn)擊“墨水濺”效果暇昂,則可以使用 InkWell莺戒。
手勢消歧
在屏幕上的給定位置處,可能存在多個(gè)手勢檢測器急波。所有這些手勢檢測器在它們經(jīng)過并且嘗試識別特定手勢時(shí)監(jiān)聽指針事件流从铲。該 GestureDetector 插件決定嘗試在此基礎(chǔ)上的回調(diào)都是非空識別哪些手勢。
當(dāng)對于屏幕上的給定指針存在多于一個(gè)手勢識別器時(shí)澄暮,框架通過使每個(gè)識別器加入手勢場來消除用戶想要的手勢名段。手勢競技場使用以下規(guī)則確定哪個(gè)手勢獲勝:
在任何時(shí)候,識別器都可以宣告失敗并離開競技場泣懊。如果競技場中只剩下一個(gè)識別器伸辟,那么識別器就是贏家。
在任何時(shí)候馍刮,識別器都可以聲明勝利信夫,這會導(dǎo)致勝利并且所有剩余的識別器都會丟失。
例如卡啰,當(dāng)消除水平和垂直拖動(dòng)的歧義時(shí)静稻,兩個(gè)識別器在接收指針向下事件時(shí)進(jìn)入競技場。識別器觀察指針移動(dòng)事件匈辱。如果用戶水平移動(dòng)指針超過一定數(shù)量的邏輯像素振湾,則水平識別器將聲明勝利并且手勢將被解釋為水平拖動(dòng)。類似地梅誓,如果用戶垂直移動(dòng)超過一定數(shù)量的邏輯像素恰梢,則垂直識別器將聲明勝利。
當(dāng)僅存在水平(或垂直)拖動(dòng)識別器時(shí)梗掰,手勢競技場是有益的嵌言。在這種情況下,競技場中將只有一個(gè)識別器及穗,并且水平拖動(dòng)將立即被識別摧茴,這意味著水平移動(dòng)的第一個(gè)像素可以被視為拖動(dòng),并且用戶將不需要等待進(jìn)一步的手勢消歧埂陆。