思考一個問題,在 Flutter 中如何處理點選、長按等手勢互動呢 ? ?
事實上,Flutter 提供了多種處理手勢互動的方案,本篇文章介紹一種比較通用和全能的方案: GestureDetector。
使用 GestureDetector 可以獲得各種型別的點選事件回撥,因此你可以建立出能夠處理各種點選事件的 Widget 來。
1.GestureDetector 常用手勢
現在,看看 GestureDetector 有些什麼常用的互動事件吧:
onTap:單擊
onDoubleTap:雙擊
onLongPress:長按
onTapUp:手指抬起來時
onTapDown:手指觸碰螢幕時
onTapCancel:點選沒有完成
onVerticalDragDown:手指剛接觸螢幕時,隨後開始垂直方向上的拖動
onVerticalDragStart:垂直方向上的拖動開始時
onVerticalDragUpdate:垂直方向上的拖動更新時
onVerticalDragEnd:垂直方向上的拖動結束時
onVerticalDragCancel:垂直拖動沒有完成
onHorizontallyDragDown:手指剛接觸螢幕時,隨後開始水平方向上的拖動
onHorizontallyDragStart:水平方向上的拖動開始時
onHorizontallyDragUpdate:水平方向上的拖動更新時
onHorizontallyDragEnd:水平方向上的拖動結束時
onHorizontallyDragCancel:水平拖動沒有完成
onScaleStart:開始縮放時,初始 scale 為 1.0
onScaleUpdate:縮放更新時
onScaleEnd:縮放結束
onPanDown:手指觸控螢幕時
onPanUpdate:手指移動時
onPanEnd:滑動結束時
2.如何使用 GestureDetector
使用 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, ), ); } } 複製程式碼
執行效果: