深入了解Android中GestureDetector的定義與使用
簡介
之前我們介紹了GestureDetector的定義和其提供的一些基本的方法,GestureDetector的好處就是可以把任何一個(gè)widget都賦予類似button的功能。
今天將會(huì)通過幾個(gè)具體的例子來講解一下GestureDetector的具體使用。
賦予widget可以點(diǎn)擊的功能
一般情況下,我們的普通widget,比如文本是不能進(jìn)行交互的,但是如果將其用GestureDetector進(jìn)行包裝之后,就可以將其偽裝成為一個(gè)button。
比如我們有這樣一個(gè)偽裝成button的Container:
Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( color: Colors.green, borderRadius: BorderRadius.circular(8.0), ), child: const Text('My Button'), )
這個(gè)Container的本質(zhì)是一個(gè)Text,這個(gè)Container本身是沒有交互功能的,那么如何對其添加交互功能呢?
最簡單的辦法就是將其使用GestureDetector包裝起來,如下所示:
GestureDetector( // The custom button child: Container( padding: const EdgeInsets.all(12.0), decoration: BoxDecoration( color: Colors.green, borderRadius: BorderRadius.circular(8.0), ), child: const Text('My Button'), ), )
接下來我們還要為其添加對應(yīng)的手勢,這里我們添加一個(gè)onTap方法,
GestureDetector( onTap: ()=> showDialog<String>( context: context, builder: (BuildContext context) => AlertDialog( title: const Text('基本手勢'), content: const Text('這是基本的手勢,你學(xué)會(huì)了嗎?'), actions: <Widget>[ TextButton( onPressed: () => Navigator.pop(context, 'Cancel'), child: const Text('Cancel'), ), TextButton( onPressed: () => Navigator.pop(context, 'OK'), child: const Text('OK'), ), ], ), ), ...
這里onTap會(huì)調(diào)用一個(gè)showDialog來彈出一個(gè)對話框,運(yùn)行之后結(jié)果如下:
會(huì)動(dòng)的組件
在上面的例子中,我們用手去tap按鈕是沒有互動(dòng)效果的,也就是說按鈕是不會(huì)變化的。
那么有沒有可能模擬手指的按壓效果呢?
答案是肯定的,flutter為我們提供了一個(gè)InkWell組件,這樣手指按壓下組件會(huì)產(chǎn)生波紋的效果。
那么InkWell和GestureDetector有什么聯(lián)系呢?
InkWell和GestureDetector很類似,都提供了對手勢的支持。
在InkWell中提供了多種GestureTapCallback接口,用接收手勢的回調(diào),非常的方便。
在使用上,InkWell和GestureDetector也很類似,我們可以完全照搬GestureDetector的用法。
還是上面的例子,我們可以將GestureDetector替換成為InkWell,如下所示:
Widget build(BuildContext context) { return InkWell( onTap: () { ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text('Tap'), )); }, child: const Padding( padding: EdgeInsets.all(12.0), child: Text('Flat Button'), ), ); }
這里,為了更好的觀察手勢按壓之后的效果,這里onTap選擇展示一個(gè)flutter自帶的SnackBar。
可刪除的組件
在app中的手勢應(yīng)用上,有一個(gè)比較常見的用法就是在list列表中,向左滑動(dòng)一個(gè)item,會(huì)出現(xiàn)刪除的按鈕,這種滑動(dòng)刪除的效果,如何在flutter中實(shí)現(xiàn)呢?
flutter提供了一個(gè)Dismissible的組件來實(shí)現(xiàn)這個(gè)效果。
我們先來看下Dismissible的定義:
class Dismissible extends StatefulWidget { const Dismissible({ required Key key, required this.child, this.background, this.secondaryBackground, this.confirmDismiss, this.onResize, this.onUpdate, this.onDismissed, this.direction = DismissDirection.horizontal, this.resizeDuration = const Duration(milliseconds: 300), this.dismissThresholds = const <DismissDirection, double>{}, this.movementDuration = const Duration(milliseconds: 200), this.crossAxisEndOffset = 0.0, this.dragStartBehavior = DragStartBehavior.start, this.behavior = HitTestBehavior.opaque, }) : assert(key != null), assert(secondaryBackground == null || background != null), assert(dragStartBehavior != null), super(key: key);
可以看到Dismissible是一個(gè)StatefulWidget,它有兩個(gè)必須的參數(shù)分別是key和child。
key用來標(biāo)記要?jiǎng)h除item的id,child是可以滑動(dòng)刪除的組件。
為了演示方便,我們使用ListView來展示如何使用Dismissible。
首先我們構(gòu)建一個(gè)items的list,里面包含了每個(gè)item要展示的內(nèi)容:
final items = List<String>.generate(10, (i) => '動(dòng)物 ${i + 1}');
然后使用ListView的builder方法來構(gòu)建items。并且將每個(gè)items封裝到Dismissible中去:
body: ListView.builder( itemCount: items.length, itemBuilder: (context, index) { final item = items[index]; return Dismissible( key: Key(item), onDismissed: (direction) { setState(() { items.removeAt(index); }); ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text('$item 被刪除了'))); }, child: ListTile( title: Text(item), ), ); }, )
這里Dismissible的child是ListTile組件,里面的具體內(nèi)容就是Text。
現(xiàn)在Dismissible實(shí)際上就可以工作了,當(dāng)你滑動(dòng)ListTile的時(shí)候,對應(yīng)的item就會(huì)被刪除。
為了明顯起見,我們可以給Dismissible添加一個(gè)background屬性,這樣滑動(dòng)刪除的時(shí)候就有了一個(gè)背景顏色:
background: Container(color: Colors.red),
另外,Dismissible還有一個(gè)confirmDismiss屬性,可以用來判斷是否真的要滑動(dòng)刪除,比如我們只允許從右到左滑動(dòng)刪除,那么可以這樣做:
Dismissible( ... confirmDismiss:confirmResult, ... ) Future<bool> confirmResult(DismissDirection direction) async { if(direction == DismissDirection.endToStart){ return true; } return false; }
這里的confirmResult是一個(gè)異步函數(shù),它接收一個(gè)DismissDirection的參數(shù),這個(gè)參數(shù)表示的是滑動(dòng)刪除的方向,我們可以通過這個(gè)方向來判斷是否真正的進(jìn)行刪除操作。
總結(jié)
以上就是日常手勢的基本使用了,我們可以通過GestureDetector,InkWell和Dismissible來和手勢進(jìn)行結(jié)合來實(shí)現(xiàn)相應(yīng)的功能。
到此這篇關(guān)于深入了解Android中GestureDetector的定義與使用的文章就介紹到這了,更多相關(guān)Android GestureDetector內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 實(shí)現(xiàn)背景圖和狀態(tài)欄融合方法
下面小編就為大家分享一篇Android 實(shí)現(xiàn)背景圖和狀態(tài)欄融合方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Android TelephonyManager詳解及實(shí)現(xiàn)代碼
本文主要介紹Android TelephonyManager, 這里整理了關(guān)于Android TelephoneManager的相關(guān)資料,并附有示例代碼和實(shí)現(xiàn)效果圖,有需要的朋友可以參考下2016-08-08Android實(shí)現(xiàn)滑動(dòng)屏幕切換圖片
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)滑動(dòng)屏幕切換圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08Android Studio 當(dāng)build時(shí)候出錯(cuò)解決辦法
這篇文章主要介紹了 Android Studio在build的時(shí)候出現(xiàn)transformClassesWithDexForDebug錯(cuò)誤解決辦法的相關(guān)資料,需要的朋友可以參考下2017-05-05Android實(shí)現(xiàn)Activity水平和垂直滾動(dòng)條的方法
這篇文章主要介紹了Android實(shí)現(xiàn)Activity水平和垂直滾動(dòng)條的方法,涉及Activity的ScrollView設(shè)置相關(guān)技巧,需要的朋友可以參考下2016-07-07