日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

监听手指是否离开屏幕android_Flutter事件监听

發(fā)布時(shí)間:2024/7/23 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 监听手指是否离开屏幕android_Flutter事件监听 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一. 事件監(jiān)聽(tīng)

在大前端的開(kāi)發(fā)中,必然存在各種各樣和用戶交互的情況:比如手指點(diǎn)擊、手指滑動(dòng)、雙擊、長(zhǎng)按等等。
所有內(nèi)容首發(fā)于公眾號(hào):coderwhy

在Flutter中,手勢(shì)有兩個(gè)不同的層次:

  • 第一層:原始指針事件(Pointer Events):描述了屏幕上由觸摸板、鼠標(biāo)、指示筆等觸發(fā)的指針的位置和移動(dòng)。
  • 第二層:手勢(shì)識(shí)別(Gesture Detector):這個(gè)是在原始事件上的一種封裝。
    • 比如我們要監(jiān)聽(tīng)用戶長(zhǎng)按,如果自己封裝原始事件我們需要監(jiān)聽(tīng)從用戶按下到抬起的時(shí)間來(lái)判斷是否是一次長(zhǎng)按事件;
    • 比如我們需要監(jiān)聽(tīng)用戶雙擊事件,我們需要自己封裝監(jiān)聽(tīng)用戶兩次按下抬起的時(shí)間間隔;
    • 幸運(yùn)的是各個(gè)平臺(tái)幾乎都對(duì)它們進(jìn)行了封裝,而Flutter中的手勢(shì)識(shí)別就是對(duì)原始指針事件的封裝;
    • 包括哪些手勢(shì)呢?比如點(diǎn)擊、雙擊、長(zhǎng)按、拖動(dòng)等

2.1. 指針事件Pointer

Pointer 代表的是人機(jī)界面交互的原始數(shù)據(jù)。一共有四種指針事件:

  • PointerDownEvent 指針在特定位置與屏幕接觸
  • PointerMoveEvent 指針從屏幕的一個(gè)位置移動(dòng)到另外一個(gè)位置
  • PointerUpEvent 指針與屏幕停止接觸
  • PointerCancelEvent 指針因?yàn)橐恍┨厥馇闆r被取消

Pointer的原理是什么呢?

  • 在指針落下時(shí),框架做了一個(gè) hit test 的操作,確定與屏幕發(fā)生接觸的位置上有哪些Widget以及分發(fā)給最內(nèi)部的組件去響應(yīng);
  • 事件會(huì)沿著最內(nèi)部的組件向組件樹(shù)的根冒泡分發(fā);
  • 并且不存在用于取消或者停止指針事件進(jìn)一步分發(fā)的機(jī)制;

原始指針事件使用Listener來(lái)監(jiān)聽(tīng):

class HomeContent extends StatelessWidget {@overrideWidget build(BuildContext context) {return Center(child: Listener(child: Container(width: 200,height: 200,color: Colors.red,),onPointerDown: (event) => print("手指按下:$event"),onPointerMove: (event) => print("手指移動(dòng):$event"),onPointerUp: (event) => print("手指抬起:$event"),),);} }

2.2. 手勢(shì)識(shí)別Gesture

Gesture是對(duì)一系列Pointer的封裝,官方建議開(kāi)發(fā)中盡可能使用Gesture,而不是Pointer

Gesture分層非常多的種類:

點(diǎn)擊:

  • onTapDown:用戶發(fā)生手指按下的操作
  • onTapUp:用戶發(fā)生手指抬起的操作
  • onTap:用戶點(diǎn)擊事件完成
  • onTapCancel:事件按下過(guò)程中被取消

雙擊:

  • onDoubleTap:快速點(diǎn)擊了兩次

長(zhǎng)按:

  • onLongPress:在屏幕上保持了一段時(shí)間

縱向拖拽:

  • onVerticalDragStart:指針和屏幕產(chǎn)生接觸并可能開(kāi)始縱向移動(dòng);
  • onVerticalDragUpdate:指針和屏幕產(chǎn)生接觸,在縱向上發(fā)生移動(dòng)并保持移動(dòng);
  • onVerticalDragEnd:指針和屏幕產(chǎn)生接觸結(jié)束;

橫線拖拽:

  • onHorizontalDragStart:指針和屏幕產(chǎn)生接觸并可能開(kāi)始橫向移動(dòng);
  • onHorizontalDragUpdate:指針和屏幕產(chǎn)生接觸,在橫向上發(fā)生移動(dòng)并保持移動(dòng);
  • onHorizontalDragEnd:指針和屏幕產(chǎn)生接觸結(jié)束;

移動(dòng):

  • onPanStart:指針和屏幕產(chǎn)生接觸并可能開(kāi)始橫向移動(dòng)或者縱向移動(dòng)。如果設(shè)置了 onHorizontalDragStart 或者 onVerticalDragStart,該回調(diào)方法會(huì)引發(fā)崩潰;
  • onPanUpdate:指針和屏幕產(chǎn)生接觸,在橫向或者縱向上發(fā)生移動(dòng)并保持移動(dòng)。如果設(shè)置了 onHorizontalDragUpdate 或者 onVerticalDragUpdate,該回調(diào)方法會(huì)引發(fā)崩潰。
  • onPanEnd:指針先前和屏幕產(chǎn)生了接觸,并且以特定速度移動(dòng),此后不再在屏幕接觸上發(fā)生移動(dòng)。如果設(shè)置了 onHorizontalDragEnd 或者 onVerticalDragEnd,該回調(diào)方法會(huì)引發(fā)崩潰。

從Widget的層面來(lái)監(jiān)聽(tīng)手勢(shì),我們需要使用:GestureDetector

  • 當(dāng)然,我們也可以使用RaisedButton、FlatButton、InkWell等來(lái)監(jiān)聽(tīng)手勢(shì)
  • globalPosition用于獲取相對(duì)于屏幕的位置信息
  • localPosition用于獲取相對(duì)于當(dāng)前Widget的位置信息
class HYHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("手勢(shì)測(cè)試"),),body: GestureDetector(child: Container(width: 200,height: 200,color: Colors.red,),onTap: () {},onTapDown: (detail) {print(detail.globalPosition);print(detail.localPosition);},onTapUp: (detail) {print(detail.globalPosition);print(detail.localPosition);}),);} }

二. 跨組件事件

在組件之間如果有事件需要傳遞,一方面可以一層層來(lái)傳遞,另一方面我們也可以使用一個(gè)EventBus工具來(lái)完成。

其實(shí)EventBus在Vue、React中都是一種非常常見(jiàn)的跨組件通信的方式:

  • EventBus相當(dāng)于是一種訂閱者模式,通過(guò)一個(gè)全局的對(duì)象來(lái)管理;
  • 這個(gè)EventBus我們可以自己實(shí)現(xiàn),也可以使用第三方的EventBus;

這里我們直接選擇第三方的EventBus:

dependencies:event_bus: ^1.1.1

第一:我們需要定義一個(gè)希望在組件之間傳遞的對(duì)象:

  • 我們可以稱之為一個(gè)時(shí)間對(duì)象,也可以是我們平時(shí)開(kāi)發(fā)中用的模型對(duì)象(model)
class UserInfo {String nickname;int level;UserInfo(this.nickname, this.level); }

第二:創(chuàng)建一個(gè)全局的EventBus對(duì)象

final eventBus = EventBus();

第三:在某個(gè)Widget中,發(fā)出事件:

class HYButton extends StatelessWidget {@overrideWidget build(BuildContext context) {return RaisedButton(child: Text("HYButton"),onPressed: () {final info = UserInfo("why", 18);eventBus.fire(info);},);} }

第四:在某個(gè)Widget中,監(jiān)聽(tīng)事件

class HYText extends StatefulWidget {@override_HYTextState createState() => _HYTextState(); }class _HYTextState extends State<HYText> {String message = "Hello Coderwhy";@overridevoid initState() {super.initState();eventBus.on<UserInfo>().listen((data) {setState(() {message = "${data.nickname}-${data.level}";});});}@overrideWidget build(BuildContext context) {return Text(message, style: TextStyle(fontSize: 30),);} } 備注:所有內(nèi)容首發(fā)于公眾號(hào),之后除了Flutter也會(huì)更新其他技術(shù)文章,TypeScript、React、Node、uniapp、mpvue、數(shù)據(jù)結(jié)構(gòu)與算法等等,也會(huì)更新一些自己的學(xué)習(xí)心得等,歡迎大家關(guān)注

總結(jié)

以上是生活随笔為你收集整理的监听手指是否离开屏幕android_Flutter事件监听的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。