一个能识别手势的 widget。相比于 Listener,GestureDetector,更加常用。
GestureDetector 介绍
GestureDetector 就不分析源码了,有兴趣的同学可以读下这篇 从源码看flutter(五):GestureDetector篇。简单的介绍下,GestureDetector 是一个 StateFulWidget,内部调用 RawGestureDetector,RawGestureDetector 又调用 Listener 监听 onPointerDown 和 onPointerPanZoomStart 事件。GestureDetector 作用仅是简化 RawGestureDetector 的使用。作为平时使用 GestureDetector 的功能就足够了。哪天如果不能满足的时候,再去找 RawGestureDetector。
使用 GestureDetector
GestureDetector 使用了很多手势识别器,最常用的就是 TapGestureRecognizer
了,使用起来很简单。
GestureDetector( onTap: () { print('tap'); }, child: Container( width: 100, height: 100, color: Colors.blue, )) 复制代码
如果没有 child 要响应 pointer 事件,需要指定 behavior。
GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { debugPrint('tap'); }, ); 复制代码
opaque 的含义在 Listener 中有讲。
其它手势也都一样,使用还是很简单的,真正需要我们关心的是手势冲突。
有多个手势竞争的时候,child 的手势会胜出
GestureDetector( onTap: () { debugPrint('tap parent'); }, child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { debugPrint('tap child'); }, ), ); 复制代码
只输出 tap child。 当 parent 和 child 同时响应 onTap 时, child 胜出。当有多个手势参与竞争的时候,需要竞技场管理者进行裁决。当 pointer up 事件发出的时候,竞技场管理者判定第一个位置的 tap 手势选手胜出。在执行 hitTest 的时候,是深度优先,所以 child 会先加入 结果列表,位置一定在 parent 前面。
pointer move 事件会打断 tap
GestureDetector( behavior: HitTestBehavior.opaque, onHorizontalDragEnd: (details) { debugPrint('darg end'); }, onTapDown: (details) { debugPrint('tap down'); }, onTap: () { debugPrint('tap'); }, ); 复制代码
如果有滑动手势胜出,输出 “tap down” 和 “move end”。
pointer down 后在一定时间内滑动超过一定距离,那么就会被判定为 PointerMoveEvent,tap 手势被移出竞技场。tapUp 和 tap 事件不会再响应。tapDown 会响应,因为 tapDown 在 pointerDownEvent 的时候就被裁决出来了。
同时存在 tap ,doubleTap
只有 tap 的时候,pointer up 的时候,立即执行,如果同时存在 double tap,需要等上 300ms,因为要判断是否要响应 double tap。tap ,doubleTap 只能有一个胜出。
同时存在 tap ,onLongPress
如果同时存在 tap,onLongPress,需要等上 500ms,因为要判断是否要响应 longPress。tap ,onLongPress 只能有一个胜出。
虽然只举这几个例子,但当多个手势竞争的时候必然会有冲突,解决冲突可以用 Listener 替代。