在Flutter中,手势有两个不同的层次:
第一层:原始指针事件(Pointer Events)
第二层:手势识别(Gesture Detector)
其原理是什么?
1 在指针落下的时候,框架做了一个hit test 的操作,确定与屏幕发生接触的位置有哪些的Widget 以及分发给最内部的组件去响应
2 事件会沿着最内部的组件向组件树的根冒泡分发
3 并且不存在用于取消或者停止指针事件进一步分发的机制
class _EventPointerDemoPageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("事件监听"),
),
body: Center(
child: Listener(
onPointerDown: (event) {
// 相对于这个container 的 位置
print(event.localPosition);
// 相对于屏幕的位置
print(event.position);
// print("手指按下了$event");
},
onPointerMove: (event) {
// print("手指移动了$event");
},
onPointerUp: (event) {
// print("手指抬起了$event");
},
child: Container(
width: 200,
height: 200,
color: Colors.redAccent,
),
)),
);
}
}
手势识别Gesture 是对一系列Pointer的封装,官方建议尽可能使用Gesture
onTapDown | 用户发生手指按下的操作 |
onTapUp | 用户发生手指抬起的操作 |
onTap | 用户点击事件完成 |
onTapCancel | 事件按下过程中被取消 |
onDoubleTap | 快速点击了两次 |
onLongPress | 在屏幕上保持了一段时间 |
onVerticalDragStart | 指针和屏幕产生接触并可能开始纵向移动; |
onVerticalDragUpdate | 指针和屏幕产生接触,在纵向上发生移动并保持移动; |
onVerticalDragEnd | 指针和屏幕产生接触结束 |
onHorizontalDragStart | 指针和屏幕产生接触并可能开始横向移动; |
onHorizontalDragUpdate | 指针和屏幕产生接触,在横向上发生移动并保持移动 |
onHorizontalDragEnd | 指针和屏幕产生接触结束; |
onPanStart | 指针和屏幕产生接触并可能开始横向移动或者纵向移动。如果设置了 onHorizontalDragStart 或者 onVerticalDragStart ,该回调方法会引发崩溃 |
onPanUpdate | 指针和屏幕产生接触,在横向或者纵向上发生移动并保持移动。如果设置了 onHorizontalDragUpdate 或者 onVerticalDragUpdate ,该回调方法会引发崩溃。 |
onPanEnd | 指针先前和屏幕产生了接触,并且以特定速度移动,此后不再在屏幕接触上发生移动。如果设置了 onHorizontalDragEnd 或者 onVerticalDragEnd ,该回调方法会引发崩溃。 |
基本使用
_gestureDemo() {
return GestureDetector(
onTap: () {
print("点击事件完成了");
},
onPanEnd: (details) {
print(details);
},
onTapDown: (details) {
// 相对于container
print(details.localPosition);
// 相对于屏幕的
print(details.globalPosition);
},
onTapUp: (details) {
// 抬起之后 才会调用 onTap ,证明点击事件完成了
print("1111");
},
child: Container(
width: 200,
height: 200,
color: Colors.blueAccent,
),
);
}
多重组件的事件传递使用的是EventBus,很方便。
官方建议我们定义不同的Event ,从而区别不同的event
使用的是插件event_bus ,简单 的三步走操作
1 创建全局的event_bus,
import "package:event_bus/event_bus.dart";
// 定义一个全局的eventBus
final eventBus = EventBus();
class MyEventMessage {
String? name;
String? action;
MyEventMessage(this.name, this.action);
}
2 fire
return ElevatedButton(
onPressed: () {
print("点击事件");
// 第二步fire
eventBus.fire(MyEventMessage("leonardo", "hahaha"));
},
child: Text("改变文字"));
}
3 listen
void initState() {
// TODO: implement initState
super.initState();
// 第三步监听操作
eventBus.on().listen((event) {
print(event.name);
setState(() {
_name = event.name!;
});
});
}