手势识别

人间烟火/张佳伟版 Lv2
手势识别 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){
//打印滑动结束时在x、y轴上的速度
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(() {
//缩放倍数在0.8到10倍之间
_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() {
//用到GestureRecognizer的话一定要调用其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;
});
},
),
  • Title: 手势识别
  • Author: 人间烟火/张佳伟版
  • Created at: 2024-05-15 16:20:42
  • Updated at: 2024-05-22 22:43:02
  • Link: https://945912035.github.io/2024/05/15/2024-05-15.1/
  • License: This work is licensed under CC BY-NC-SA 4.0.
 Comments
On this page
手势识别