1 指针事件 Pointer
Pointer 代表的是人机界面交互的原始数据。一共有四种指针事件:
- PointerDownEvent 指针在特定位置与屏幕接触
- PointerMoveEvent 指针从屏幕的一个位置移动到另外一个位置
- PointerUpEvent 指针与屏幕停止接触
- PointerCancelEvent 指针因为一些特殊情况被取消
Pointer的原理是什么呢?
- 在指针落下时,框架做了一个 hit test 的操作,确定与屏幕发生接触的位置上有哪些Widget以及分发给最内部的组件去响应;
- 事件会沿着最内部的组件向组件树的根冒泡分发;
不存在用于取消或者停止指针事件进一步分发的机制;
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Listener(
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
onPointerDown: (event) {
print("手指按下:$event");
print(event.position); // 用于获取相对于屏幕的位置信息
print(event.localPosition); // 获取相对于当前Widget的位置信息
},
onPointerMove: (event) => print("手指移动:$event"),
onPointerUp: (event) => print("手指抬起:$event"),
),
);
}
}
2 手势识别 Gesture
Gesture是对一系列Pointer的封装,官方建议开发中尽可能使用Gesture,而不是Pointer
从Widget的层面来监听手势,我们需要使用:GestureDetector点击:
- onTapDown:用户发生手指按下的操作
- onTapUp:用户发生手指抬起的操作
- onTap:用户点击事件完成
- onTapCancel:事件按下过程中被取消
- 双击:
- onDoubleTap:快速点击了两次
- 长按:
- onLongPress:在屏幕上保持了一段时间
- 纵向拖拽:
- onVerticalDragStart:指针和屏幕产生接触并可能开始纵向移动;
- onVerticalDragUpdate:指针和屏幕产生接触,在纵向上发生移动并保持移动;
- onVerticalDragEnd:指针和屏幕产生接触结束;
- 横线拖拽:
- onHorizontalDragStart:指针和屏幕产生接触并可能开始横向移动;
- onHorizontalDragUpdate:指针和屏幕产生接触,在横向上发生移动并保持移动;
- onHorizontalDragEnd:指针和屏幕产生接触结束;
移动:
- onPanStart:指针和屏幕产生接触并可能开始横向移动或者纵向移动。如果设置了 onHorizontalDragStart 或者 onVerticalDragStart,该回调方法会引发崩溃;
- onPanUpdate:指针和屏幕产生接触,在横向或者纵向上发生移动并保持移动。如果设置了 onHorizontalDragUpdate 或者 onVerticalDragUpdate,该回调方法会引发崩溃。
- onPanEnd:指针先前和屏幕产生了接触,并且以特定速度移动,此后不再在屏幕接触上发生移动。如果设置了 onHorizontalDragEnd 或者 onVerticalDragEnd,该回调方法会引发崩溃。 ```dart class HomeContent extends StatelessWidget { const HomeContent({Key? key}) : super(key: key);
@override Widget build(BuildContext context) { return Center(
child: GestureDetector(
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
onTap: () {
print("tap");
},
onTapDown: (detail) {
print(detail.globalPosition);
print(detail.localPosition);
},
onTapUp: (detail) {
print(detail.globalPosition);
print(detail.localPosition);
}
),
3 跨组件事件 EventBus
在组件之间如果有事件需要传递,一方面可以一层层来传递,另一方面我们也可以使用一个EventBus工具来完成。
EventBus相当于是一种订阅者模式,通过一个全局的对象来管理;
这个EventBus我们可以自己实现,也可以使用第三方的EventBus;
这里我们直接选择第三方的EventBus:
dependencies:
event_bus:^1.1.1
class HomeContent extends StatelessWidget {
const HomeContent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Row(
children: [
MyText(),
MyButton()
]
),
);
}
}
class UserInfo {
String nickname;
int level;
UserInfo(this.nickname, this.level);
}
final eventBus = EventBus();
class MyButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ElevatedButton(
child: Text("MyButton"),
onPressed: () {
final info = UserInfo("ws", 18);
eventBus.fire(info);
},
);
}
}
class MyText extends StatefulWidget {
const MyText({ Key? key }) : super(key: key);
@override
State<MyText> createState() => _MyTextState();
}
class _MyTextState extends State<MyText> {
String message = "Hello ws";
@override
void initState() {
super.initState();
eventBus.on<UserInfo>().listen((data) {
setState(() {
message = "${data.nickname}-${data.level}";
});
});
}
@override
Widget build(BuildContext context) {
return Text(message, style: TextStyle(fontSize: 30),);;
}
}