1 指针事件 Pointer
Pointer 代表的是人机界面交互的原始数据。一共有四种指针事件:
- PointerDownEvent 指针在特定位置与屏幕接触
- PointerMoveEvent 指针从屏幕的一个位置移动到另外一个位置
- PointerUpEvent 指针与屏幕停止接触
- PointerCancelEvent 指针因为一些特殊情况被取消
Pointer的原理是什么呢?
- 在指针落下时,框架做了一个 hit test 的操作,确定与屏幕发生接触的位置上有哪些Widget以及分发给最内部的组件去响应;
- 事件会沿着最内部的组件向组件树的根冒泡分发;
不存在用于取消或者停止指针事件进一步分发的机制;
class HomeContent extends StatelessWidget {const HomeContent({Key? key}) : super(key: key);@overrideWidget 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);@overrideWidget 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 {@overrideWidget 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);@overrideState<MyText> createState() => _MyTextState();}class _MyTextState extends State<MyText> {String message = "Hello ws";@overridevoid initState() {super.initState();eventBus.on<UserInfo>().listen((data) {setState(() {message = "${data.nickname}-${data.level}";});});}@overrideWidget build(BuildContext context) {return Text(message, style: TextStyle(fontSize: 30),);;}}
