簡介
之前我們介紹了GestureDetector的定義和其提供的一些基本的方法,GestureDetector的好處就是可以把任何一個widget都賦予類似button的功能。
今天將會透過幾個具體的例子來講解一下GestureDetector的具體使用。
賦予widget可以點選的功能
一般情況下,我們的普通widget,比如文字是不能進行互動的,但是如果將其用GestureDetector進行包裝之後,就可以將其偽裝成為一個button。
比如我們有這樣一個偽裝成button的Container:
Container(
padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(8.0),
),
child: const Text('My Button'),
)
這個Container的本質是一個Text,這個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'),
),
)
接下來我們還要為其新增對應的手勢,這裡我們新增一個onTap方法,
GestureDetector(
onTap: ()=> showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('基本手勢'),
content: const Text('這是基本的手勢,你學會了嗎?'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
),
),
...
這裡onTap會呼叫一個showDialog來彈出一個對話方塊,執行之後結果如下:
會動的元件
在上面的例子中,我們用手去tap按鈕是沒有互動效果的,也就是說按鈕是不會變化的。
那麼有沒有可能模擬手指的按壓效果呢?
答案是肯定的,flutter為我們提供了一個InkWell元件,這樣手指按壓下元件會產生波紋的效果。
那麼InkWell和GestureDetector有什麼聯絡呢?
InkWell和GestureDetector很類似,都提供了對手勢的支援。
在InkWell中提供了多種GestureTapCallback介面,用接收手勢的回撥,非常的方便。
在使用上,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選擇展示一個flutter自帶的SnackBar。
可刪除的元件
在app中的手勢應用上,有一個比較常見的用法就是在list列表中,向左滑動一個item,會出現刪除的按鈕,這種滑動刪除的效果,如何在flutter中實現呢?
flutter提供了一個Dismissible的元件來實現這個效果。
我們先來看下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是一個StatefulWidget,它有兩個必須的引數分別是key和child。
key用來標記要刪除item的id,child是可以滑動刪除的元件。
為了演示方便,我們使用ListView來展示如何使用Dismissible。
首先我們構建一個items的list,裡面包含了每個item要展示的內容:
final items = List<String>.generate(10, (i) => '動物 ${i + 1}');
然後使用ListView的builder方法來構建items。並且將每個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元件,裡面的具體內容就是Text。
現在Dismissible實際上就可以工作了,當你滑動ListTile的時候,對應的item就會被刪除。
為了明顯起見,我們可以給Dismissible新增一個background屬性,這樣滑動刪除的時候就有了一個背景顏色:
background: Container(color: Colors.red),
另外,Dismissible還有一個confirmDismiss屬性,可以用來判斷是否真的要滑動刪除,比如我們只允許從右到左滑動刪除,那麼可以這樣做:
Dismissible(
...
confirmDismiss:confirmResult,
...
)
Future<bool> confirmResult(DismissDirection direction) async {
if(direction == DismissDirection.endToStart){
return true;
}
return false;
}
這裡的confirmResult是一個非同步函式,它接收一個DismissDirection的引數,這個參數列示的是滑動刪除的方向,我們可以透過這個方向來判斷是否真正的進行刪除操作。
總結
以上就是日常手勢的基本使用了,我們可以透過GestureDetector,InkWell和Dismissible來和手勢進行結合來實現相應的功能。
本文的例子:https://github.com/ddean2009/learn-flutter.git
更多內容請參考 www.flydean.com
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!