Flutter實(shí)現(xiàn)手勢識(shí)別功能詳解方法
GestureDetector
GestureDetector 是手勢識(shí)別的組件,可以識(shí)別點(diǎn)擊、雙擊、長按事件、拖動(dòng)、縮放等手勢
點(diǎn)擊事件
點(diǎn)擊相關(guān)事件包括:
- onTapDown:按下時(shí)回調(diào)。
- onTapUp:抬起時(shí)回調(diào)。
- onTap:點(diǎn)擊事件回調(diào)。
- onTapCancel:點(diǎn)擊取消事件回調(diào)。
按下然后抬起調(diào)用順序
onTapDown-> onTapUp-> onTap
按下后移動(dòng)調(diào)用順序
onTapDown-> onTapCancel
示例
class _YcHomeBodyState extends State<YcHomeBody> { String desc = ''; Color containerColor = Colors.red; @override Widget build(BuildContext context) { return GestureDetector( child: Column( children: [ Container( width: 420, height: 330, color: containerColor, ), const SizedBox( width: 100, height: 20, ), Text("點(diǎn)擊事件:$desc") ], ), onTapDown: (TapDownDetails tapDownDetails) { setState(() { desc += '按下,'; containerColor = Colors.blue; }); }, onTapUp: (TapUpDetails tapUpDetails) { setState(() { desc += '抬起,'; containerColor = Colors.red; }); }, onTap: () { setState(() { desc += '點(diǎn)擊,'; containerColor = Colors.yellow; }); }, onTapCancel: () { setState(() { desc += '取消,'; containerColor = Colors.pink; }); }, ); } }
雙擊事件
雙擊是快速且連續(xù)2次在同一個(gè)位置點(diǎn)擊,雙擊監(jiān)聽使用onDoubleTap方法
return GestureDetector( child: Column( children: [ Container( width: 420, height: 330, color: containerColor, ), const SizedBox( width: 100, height: 20, ), Text("點(diǎn)擊事件:$desc") ], ), onDoubleTap: () { setState(() { desc = '雙擊了'; }); },
長按事件
長按事件(LongPress)包含長按開始、移動(dòng)、抬起、結(jié)束事件,說明如下:
- onLongPressStart:長按開始事件回調(diào)。
- onLongPressMoveUpdate:長按移動(dòng)事件回調(diào)。
- onLongPressUp:長按抬起事件回調(diào)。
- onLongPressEnd:長按結(jié)束事件回調(diào)。
- onLongPress:長按事件回調(diào)。
示例
return GestureDetector( child: Column( children: [ Container( width: 420, height: 330, color: containerColor, ), const SizedBox( width: 100, height: 20, ), Text("點(diǎn)擊事件:$desc") ], ), onLongPressStart: (v) { setState(() { desc += '長按開始,'; print("長按開始:$v"); }); }, onLongPressMoveUpdate: (v) { setState(() { desc += '長按移動(dòng),'; print("長按移動(dòng):$v"); }); }, onLongPressUp: () { setState(() { desc += '長按抬起,'; print("長按抬起"); }); }, onLongPressEnd: (v) { setState(() { desc += '長按結(jié)束,'; print("長按結(jié)束:$v"); }); }, onLongPress: () { setState(() { desc += '長按回調(diào),'; print("長按回調(diào)"); }); });
執(zhí)行順序
1、長按開始->回調(diào)->結(jié)束->抬起
2、長按開始->回調(diào)->移動(dòng)->結(jié)束->抬起
水平/垂直拖動(dòng)事件
垂直/水平拖動(dòng)事件包括按下、開始、移動(dòng)更新、結(jié)束、取消事件,以垂直為例說明如下:
- onVerticalDragDown:垂直拖動(dòng)按下事件回調(diào)
- onVerticalDragStart:垂直拖動(dòng)開始事件回調(diào)
- onVerticalDragUpdate:指針移動(dòng)更新事件回調(diào)
- onVerticalDragEnd:垂直拖動(dòng)結(jié)束事件回調(diào)
- onVerticalDragCancel:垂直拖動(dòng)取消事件回調(diào)
GestureDetector( onVerticalDragStart: (v) => print('onVerticalDragStart'), onVerticalDragDown: (v) => print('onVerticalDragDown'), onVerticalDragUpdate: (v) => print('onVerticalDragUpdate'), onVerticalDragCancel: () => print('onVerticalDragCancel'), onVerticalDragEnd: (v) => print('onVerticalDragEnd'), child: Center( child: Container( width: 200, height: 200, color: Colors.red, ), ), )
縮放事件
縮放(Scale)包含縮放開始、更新、結(jié)束。說明如下:
- onScaleStart:縮放開始事件回調(diào)。
- onScaleUpdate:縮放更新事件回調(diào)。
- onScaleEnd:縮放結(jié)束事件回調(diào)。
GestureDetector( onScaleStart: (v) => print('onScaleStart'), onScaleUpdate: (ScaleUpdateDetails v) => print('onScaleUpdate'), onScaleEnd: (v) => print('onScaleEnd'), child: Center( child: Container( width: 200, height: 200, color: Colors.red, ), ), )
InkWell
InkWell 組件在用戶點(diǎn)擊時(shí)出現(xiàn)“水波紋”效果。事件和屬性挺多的,就看一下常用的
設(shè)置水波紋顏色
點(diǎn)擊和長按都能夠觸發(fā)水波紋,點(diǎn)擊波紋效果快,長按波紋效果慢
return InkWell( onTap: (){ print("點(diǎn)擊了"); }, splashColor: Colors.red, child: const Text('點(diǎn)擊InkWell,水波紋'), );
給字體添加邊距和圓角邊框,擴(kuò)大“水波紋”效果:
Center( child: InkWell( onTap: () { print("點(diǎn)擊了"); }, splashColor: Colors.red, child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( border: Border.all(color: Colors.red), borderRadius: const BorderRadius.all(Radius.circular(20))), child: const Text('點(diǎn)擊InkWell,水波紋'))), );
可以看到水波紋會(huì)超出圓角,為了解決這個(gè)問題可以使用Ink
Ink
Ink控件用于在[Material]控件上繪制圖像和其他裝飾,以便[InkWell]、[InkResponse]控件的“水波紋”效果在其上面顯示。
return Center( child: Ink( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFDE2F21), Color(0xFFEC592F)]), borderRadius: BorderRadius.all(Radius.circular(20))), child: InkWell( borderRadius: const BorderRadius.all(Radius.circular(20)), child: Container( padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20), child: const Text( '這是InkWell的點(diǎn)擊效果', style: TextStyle(color: Colors.white), ), ), onTap: () {}, ), )); }
總感覺有點(diǎn)復(fù)雜,InkWell 會(huì)導(dǎo)致水紋超出邊框,就需要外面再套一層組件,然后還要寫個(gè)漸變,不知道咋形容。
Listener
Listener 是一個(gè)監(jiān)聽指針事件的控件,比如按下、移動(dòng)、釋放、取消等指針事件,但Listener無法監(jiān)聽鼠標(biāo)特有的事件,比如:移入、懸停、移出事件。鼠標(biāo)事件使用MouseRegion監(jiān)聽。
通常情況下,監(jiān)聽手勢事件使用GestureDetector,GestureDetector是更高級(jí)的手勢事件。
Listener的事件介紹如下:
- onPointerDown:按下時(shí)回調(diào)
- onPointerMove:移動(dòng)時(shí)回調(diào)
- onPointerUp:抬起時(shí)回調(diào)
Listener( onPointerDown: (PointerDownEvent pointerDownEvent) { print('$pointerDownEvent'); }, onPointerMove: (PointerMoveEvent pointerMoveEvent) { print('$pointerMoveEvent'); }, onPointerUp: (PointerUpEvent upEvent) { print('$upEvent'); }, child: Container( height: 200, width: 200, color: Colors.blue, alignment: Alignment.center, ), )
常用屬性說明如下:
position:相對(duì)屏幕的坐標(biāo)的偏移。
localPosition:相對(duì)當(dāng)前控件的偏移。
pressure:按壓力度。
delta:2次指針移動(dòng)事件的偏移。
orientation:指針移動(dòng)方向
案例
進(jìn)度按鈕
// 使用枚舉定義按鈕的狀態(tài) enum ButtonStates { none, loading, done } class YcHomeBody extends StatefulWidget { const YcHomeBody({Key? key}) : super(key: key); @override State<YcHomeBody> createState() => _YcHomeBodyState(); } class _YcHomeBodyState extends State<YcHomeBody> { //定義按鈕的狀態(tài) ButtonStates _buttonStates = ButtonStates.none; @override Widget build(BuildContext context) { return Center( child: MaterialButton( color: Colors.blue, textColor: Colors.white, minWidth: 200, height: 40, //通過自定義方法,根據(jù)情況返回相應(yīng)的組件 child: _build(), onPressed: () { //點(diǎn)擊按鈕后將按鈕狀態(tài)變?yōu)榧虞d中 setState(() { _buttonStates = ButtonStates.loading; //延遲2s后將狀態(tài)變?yōu)橥瓿? Future.delayed(const Duration(seconds: 2), () { setState(() { _buttonStates = ButtonStates.done; }); }); }); }, ), ); } //自定義方法 _build() { if (_buttonStates == ButtonStates.none) { //無狀態(tài) return const Text("登錄"); } else if (_buttonStates == ButtonStates.loading) { //進(jìn)度條組件 return const CircularProgressIndicator( backgroundColor: Colors.white, strokeWidth: 2, ); } else if (_buttonStates == ButtonStates.done) { return const Icon( Icons.check, color: Colors.white, ); } } }
代碼看著很長但是邏輯很簡單,定義了一個(gè)枚舉類型的按鈕類型。一開始類型為無狀態(tài),此時(shí)顯示登錄;當(dāng)點(diǎn)擊按鈕后,狀態(tài)變?yōu)榧虞d中,顯示圓形進(jìn)度條組件;2s后將按鈕狀態(tài)變?yōu)榧虞d完成,現(xiàn)成完成的圖標(biāo)
到此這篇關(guān)于Flutter實(shí)現(xiàn)手勢識(shí)別功能詳解方法的文章就介紹到這了,更多相關(guān)Flutter手勢識(shí)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android基于OkHttpUtils網(wǎng)絡(luò)請求的二次封裝
這篇文章主要介紹了Android基于OkHttpUtils網(wǎng)絡(luò)請求的二次封裝,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Flutter實(shí)現(xiàn)自定義搜索框AppBar的示例代碼
開發(fā)中,頁面頭部為搜索樣式的設(shè)計(jì)非常常見,為了可以像系統(tǒng)AppBar那樣使用,本文將利用Flutter自定義一個(gè)搜索框,感興趣的可以了解一下2022-04-04Android實(shí)現(xiàn)自動(dòng)填充短信驗(yàn)證碼功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)自動(dòng)填充短信驗(yàn)證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12Android使用相機(jī)實(shí)現(xiàn)拍照存儲(chǔ)及展示功能詳解
這篇文章主要介紹了Android使用相機(jī)實(shí)現(xiàn)拍照存儲(chǔ)及展示功能,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-01-01Android 屬性動(dòng)畫原理與DataBinding
這篇文章主要介紹了Android 屬性動(dòng)畫原理與DataBinding的相關(guān)資料,需要的朋友可以參考下2017-04-04