手势识别 GestureDetector 与 GestureRecognizer
用处:可以用来识别各种手势(点击、双击、长按、滑动、拖动…)
我们通过GestureDetector对Container进行手势识别,触发相应事件后,在Container上显示事件名,为了增大点击区域,将Container设置为200×100,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class _GestureTestState extends State<GestureTest> { String _operation = "No Gesture detected!"; @override Widget build(BuildContext context) { return Center( child: GestureDetector( child: Container( alignment: Alignment.center, color: Colors.blue, width: 200.0, height: 100.0, child: Text( _operation, style: TextStyle(color: Colors.white), ), ), onTap: () => updateText("Tap"), onDoubleTap: () => updateText("DoubleTap"), onLongPress: () => updateText("LongPress"), ), ); }
void updateText(String text) { setState(() { _operation = text; }); } }
|
(当同时监听onTap和onDoubleTap事件时,当用户触发tap事件时,会有200毫秒左右的延时,如果用户只监听了onTap(没有监听onDoubleTap)事件时,则没有延时)
下面我们看一个拖动圆形字母A的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| class _Drag extends StatefulWidget { @override _DragState createState() => _DragState(); }
class _DragState extends State<_Drag> with SingleTickerProviderStateMixin { double _top = 0.0; double _left = 0.0;
@override Widget build(BuildContext context) { return Stack( children: <Widget>[ Positioned( top: _top, left: _left, child: GestureDetector( child: CircleAvatar(child: Text("A")), onPanDown: (DragDownDetails e) { print("用户手指按下:${e.globalPosition}"); }, onPanUpdate: (DragUpdateDetails e) { setState(() { _left += e.delta.dx; _top += e.delta.dy; }); }, onPanEnd: (DragEndDetails e){ print(e.velocity); }, ), ) ], ); } }
|
单一方向拖动:
1 2 3 4 5 6 7
| child: GestureDetector( child: CircleAvatar(child: Text("A")), onVerticalDragUpdate: (DragUpdateDetails details) { setState(() { _top += details.delta.dy; });
|
缩放 GestureDetector – onScaleUpdate
1 2 3 4 5 6 7 8
| child: GestureDetector( child: Image.asset("./images/sea.png", width: _width), onScaleUpdate: (ScaleUpdateDetails details) { setState(() { _width=200*details.scale.clamp(.8, 10.0); });
|
GestureRecognizer
1、GestureDetector内部是使用一个或多个GestureRecognizer来识别各种手势的
2、GestureDetector直接可以接收一个子widget
3、GestureRecognizer的作用就是通过Listener来将原始指针事件转换为语义手
4、GestureRecognizer是一个抽象类,一种手势的识别器对应一个GestureRecognizer的子类
假设我们要给一段富文本(RichText)的不同部分分别添加点击事件处理器
但是TextSpan并不是一个widget,这时我们不能用GestureDetector,
但TextSpan有一个recognizer属性,它可以接收一个GestureRecognizer
1 2 3 4 5 6 7 8
| TapGestureRecognizer _tapGestureRecognizer = TapGestureRecognizer();
@override void dispose() { _tapGestureRecognizer.dispose(); super.dispose(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| TextSpan( text: "点我变色", style: TextStyle( fontSize: 30.0, color: _toggle ? Colors.blue : Colors.red, ), recognizer: _tapGestureRecognizer ..onTap = () { setState(() { _toggle = !_toggle; }); }, ),
|