思考一個問題,在 Flutter 中如何處理點擊、長按等手勢交互呢 🤔 ?github
事實上,Flutter 提供了多種處理手勢交互的方案,本篇文章介紹一種比較通用和全能的方案: GestureDetector。bash
使用 GestureDetector 能夠得到各類類型的點擊事件回調,所以你能夠建立出可以處理各類點擊事件的 Widget 來。ide
如今,看看 GestureDetector 有些什麼經常使用的交互事件吧:函數
onTap:單擊post
onDoubleTap:雙擊ui
onLongPress:長按this
onTapUp:手指擡起來時spa
onTapDown:手指觸碰屏幕時3d
onTapCancel:點擊沒有完成
onVerticalDragDown:手指剛接觸屏幕時,隨後開始垂直方向上的拖動
onVerticalDragStart:垂直方向上的拖動開始時
onVerticalDragUpdate:垂直方向上的拖動更新時
onVerticalDragEnd:垂直方向上的拖動結束時
onVerticalDragCancel:垂直拖動沒有完成
onHorizontallyDragDown:手指剛接觸屏幕時,隨後開始水平方向上的拖動
onHorizontallyDragStart:水平方向上的拖動開始時
onHorizontallyDragUpdate:水平方向上的拖動更新時
onHorizontallyDragEnd:水平方向上的拖動結束時
onHorizontallyDragCancel:水平拖動沒有完成
onScaleStart:開始縮放時,初始 scale 爲 1.0
onScaleUpdate:縮放更新時
onScaleEnd:縮放結束
onPanDown:手指觸摸屏幕時
onPanUpdate:手指移動時
onPanEnd:滑動結束時
使用 GestureDetector 建立一個可交互的 Widget。
class TapBox extends StatefulWidget {
final bool active;
// 定義一個函數,外界傳入後可被調用
final ValueChanged<bool> onChanged;
TapBox({Key key, this.active, this.onChanged}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _TabBox();
}
}
class _TabBox extends State<TapBox> {
bool _highlight = false;
void _handleTapDown(TapDownDetails details) {
setState(() {
_highlight = true;
});
}
void _handleTapUp(TapUpDetails details) {
setState(() {
_highlight = false;
});
}
void _handleTapCancel() {
setState(() {
_highlight = false;
});
}
void _handleTap() {
// 經過 widget 能夠得到其成員變量
widget.onChanged(!widget.active);
}
Widget build(BuildContext context) {
// 把你的 Widget 使用 GestureDetector 包裹📦起來
return GestureDetector(
// 處理按下手勢
onTapDown: _handleTapDown,
// 處理擡起手勢
onTapUp: _handleTapUp,
// 處理點擊手勢
onTap: _handleTap,
// 處理取消手勢
onTapCancel: _handleTapCancel,
child: Container(
child: Center(
child: Text(widget.active ? 'Active' : 'Inactive',
style: TextStyle(fontSize: 32.0, color: Colors.white)),
),
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: widget.active ? Colors.lightGreen[700] : Colors.grey[600],
border: _highlight
? Border.all(
color: Colors.teal[700],
width: 10.0,
)
: null,
),
),
);
}
}
複製代碼
你看,GestureDetector 也是一個 Widget,經過使用它來包裹目標 Widget,就使得目標 Widget 具備處理事件的能力。
使用這個 Widget。
class ParentWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _ParentWidget();
}
}
class _ParentWidget extends State<ParentWidget> {
bool _active = false;
void _handleTapBoxChanged(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return Container(
child: TapBox(
active: _active,
// 傳入函數
onChanged: _handleTapBoxChanged,
),
);
}
}
複製代碼
運行效果: