思考一个问题,在 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, ), ); } }
运行效果: