一. 事件监听
在大前端的开发中:比如手指点击、手指滑动、双击、长按等等。
在Flutter中,手势有两个不同的层次:
- 第一层:原始指针事件(Pointer Events):描述了屏幕上由触摸板、鼠标、指示笔等触发的指针的位置和移动。
第二层:手势识别(Gesture Detector):这个是在原始事件上的一种封装。
PointerDownEvent 指针在特定位置与屏幕接触
- PointerMoveEvent 指针从屏幕的一个位置移动到另外一个位置
- PointerUpEvent 指针与屏幕停止接触
- PointerCancelEvent 指针因为一些特殊情况被取消
Pointer的原理是什么呢?
- 在指针落下时,框架做了一个 hit test 的操作,确定与屏幕发生接触的位置上有哪些Widget以及分发给最内部的组件去响应;
- 事件会沿着最内部的组件向组件树的根冒泡分发;
- 并且不存在用于取消或者停止指针事件进一步分发的机制;
原始指针事件使用Listener来监听:
class HomeContent extends StatelessWidget {@overrideWidget build(BuildContext context) {return Center(child: Listener(child: Container(width: 200,height: 200,color: Colors.red,),onPointerDown: (event) => print("手指按下:$event"),onPointerMove: (event) => print("手指移动:$event"),onPointerUp: (event) => print("手指抬起:$event"),),);}}
2.2. 手势识别Gesture
Gesture是对一系列Pointer的封装,官方建议开发中尽可能使用Gesture,而不是Pointer
Gesture分层非常多的种类:
点击:
- onTapDown:用户发生手指按下的操作
- onTapUp:用户发生手指抬起的操作
- onTap:用户点击事件完成
- onTapCancel:事件按下过程中被取消
双击:
- onDoubleTap:快速点击了两次
长按:
- onLongPress:在屏幕上保持了一段时间
纵向拖拽:
- onVerticalDragStart:指针和屏幕产生接触并可能开始纵向移动;
- onVerticalDragUpdate:指针和屏幕产生接触,在纵向上发生移动并保持移动;
- onVerticalDragEnd:指针和屏幕产生接触结束;
横线拖拽:
- onHorizontalDragStart:指针和屏幕产生接触并可能开始横向移动;
- onHorizontalDragUpdate:指针和屏幕产生接触,在横向上发生移动并保持移动;
- onHorizontalDragEnd:指针和屏幕产生接触结束;
移动:
- onPanStart:指针和屏幕产生接触并可能开始横向移动或者纵向移动。如果设置了 onHorizontalDragStart 或者 onVerticalDragStart,该回调方法会引发崩溃;
- onPanUpdate:指针和屏幕产生接触,在横向或者纵向上发生移动并保持移动。如果设置了 onHorizontalDragUpdate 或者 onVerticalDragUpdate,该回调方法会引发崩溃。
- onPanEnd:指针先前和屏幕产生了接触,并且以特定速度移动,此后不再在屏幕接触上发生移动。如果设置了 onHorizontalDragEnd 或者 onVerticalDragEnd,该回调方法会引发崩溃。
从Widget的层面来监听手势,我们需要使用:GestureDetector
- 当然,也可以使用RaisedButton、FlatButton、InkWell等来监听手势
- globalPosition用于获取相对于屏幕的位置信息
localPosition用于获取相对于当前Widget的位置信息
class WLHomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("手势测试"),),body: GestureDetector(child: Container(width: 200,height: 200,color: Colors.red,),onTap: () {},onTapDown: (detail) {print(detail.globalPosition);print(detail.localPosition);},onTapUp: (detail) {print(detail.globalPosition);print(detail.localPosition);}),);}}
二. 跨组件事件
组件间有事件需要传递,可以一层层来传递,也可以使用一个EventBus工具来完成。
EventBus相当于是一种订阅者模式,通过一个全局的对象来管理;
第一:需要定义一个希望在组件之间传递的对象:
可以称之为一个时间对象,也可以是我们平时开发中用的模型对象(model)
class UserInfo {String nickname;int level;UserInfo(this.nickname, this.level);}
第二:创建一个全局的EventBus对象
final eventBus = EventBus();
第三:在某个Widget中,发出事件:
class HYButton extends StatelessWidget {@overrideWidget build(BuildContext context) {return RaisedButton(child: Text("HYButton"),onPressed: () {final info = UserInfo("why", 18);eventBus.fire(info);},);}}
第四:在某个Widget中,监听事件 ```dart class HYText extends StatefulWidget { @override _HYTextState createState() => _HYTextState(); }
class _HYTextState extends State
@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),); } } ```
