# Flutter GestureDetector/InkWell/Dismissible 介紹
## GestureDetector
為元件添加手勢,例如:
* 點擊:onTapDown、onTapUp、onTap、onTapCancel
* 雙擊:onDoubleTap
* 長按:onLongPress
* 拖動[垂直/水平]:on[Verticalon/Horizontal]DragStart、on[Verticalon/Horizontal]DragUpdate、on[Verticalon/Horizontal]DragEnd、
* 滑動:onPanStart、onPanUpdate、onPanEnd
### 屬性
#### behavior
* HitTestBehavior.deferToChild: 將觸控事件向下傳遞給小元件樹
* HitTestBehavior.opaque: 不會向下傳遞接收觸控事件給小元件樹
* HitTestBehavior.translucent: 允許後臺的小部件接收觸控事件
參考:
1. https://flutter.dev/docs/development/ui/advanced/gestures
2. https://segmentfault.com/a/1190000040706660
## InkWell
為元件添加水波紋效果(如圖)

### 範例程式碼
```dart
InkWell(
child: GroceryTile(
key: Key(item.id),
item: item,
onComplete: (change) {
manager.completeItem(index, change!);
}),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GroceryItemScreen(
originalItem: item,
onUpdate: (item) {
manager.updateItem(item, index);
Navigator.pop(context);
},
onCreate: (_) {},
),
),
);
},
)
```
### 例外狀況也可以使用Ink
有些時候,使用 Image 或為 Container 設置顏色之後,水波紋就會無法觸發,可改採Ink。
```dart
Widget buildContent() {
return Ink(
width: 200,
height: 0.618 * 200,
decoration: const BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage('assets/images/anim_draw.webp'))),
child: Padding(
padding: const EdgeInsets.all(20),
child: Text("Card: 卡片",
style: TextStyle(fontSize: 20,color: Colors.white)),
));
}
```
## Dismissible
當用戶向左或向右滑動(或垂直滑動)時從列表中清除項目的小部件(如圖)

### 屬性
* `key` 每个Dismissible實例都必須包含一個Key。Key讓Flutter能夠對Widgets做唯一標示。
* `direction` 甚麼樣的滑動方向觸發`onDismissed`
```dart
enum DismissDirection {
vertical,
horizontal,
endToStart,
startToEnd,
up,
down,
none
}
```
* `onDismissed` 判斷所設定的`direction`是否符合,若符合被移除項目須做甚麼事情。
* `background` 滑動時跑出來的背景色(左滑)
* `secondaryBackground` 滑動時跑出來的背景色(右滑),若未設定則使用`background`的顏色
* `resizeDuration` 滑動消失時,下方項目會有一個**上移**的動畫,該動畫時間長度
* `onResize ` 會在動畫執行的每幀中進行callback。
* `dismissThresholds` 表示滑動超過特定百分比觸發`onDismissed`,預設0.4
* `movementDuration` 水平移動至消失的動畫時間
### 範例程式碼
```dart
Dismissible(
key: Key(item.id),
direction: DismissDirection.endToStart,
background: Container(
color: Colors.red,
alignment: Alignment.centerRight,
child: const Icon(Icons.delete_forever,
color: Colors.white, size: 50.0)),
onDismissed: (direction) {
manager.deleteItem(index);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('${item.name} dismissed')));
}
```
###### tags: `flutter`