1 手指按下
手指按下会做以下几件事
1.1 进行hitTest 从根节点一级一级的进行hitTest 找到所有可以处理这个事件的 RenderObject,RendObject 实现了HitTestTarget,所以也可以说找到所有能处理这个事件的 HitTestTarget,最终返回HitTestResult,HitTestResult的path 里面保存了所有命中的RenderObject。
1.2 依次调用所有命中的RendObject(HitTestTarget) 的 handleEvent
2 手指按下之后的事件都是通过 PointerRouter.route
下发的。并不直接再次调用最终返回HitTestResult
中保存的RenderObject
的handleEvent
方法。所以命中的RenderObject
能不能接收到后续的事件由PointerRouter决定。
3 我们一般是使用GestureDetector
来进行事件的注册。
3.1 我们来简单捋一下 GestureDetector
- build - RawGestureDetector
- RawGestureDetectorState
- build - Listener
3.2 最终我们定位到Listener
组建,Listener
组建是个RenderObjectWidget
,所以他也是有对应的RenderObject
,在对应的RenderObject
的handleEvent
方法中收到down
事件的时候,Listener
的onPointerDown
会执行
4 我们接着分析Listener的onPointerDown方法
scss
void _handlePointerDown(PointerDownEvent event) {
assert(_recognizers != null);
for (final GestureRecognizer recognizer in _recognizers!.values) {
recognizer.addPointer(event);
}
}
这个地方的 _recognizers 我们不纠结,就理解成我们我们在使用GestureDetector
注册事件的时候,根据注册的事件会生成不同GestureRecognizer
,真正判断这个事件是单击还是长按,具体逻辑都在对应的GestureRecognizer
实现类里面。
我们看addPoint方法。如果处理这个事件就会继续走 addAllowedPointer
csharp
void addPointer(PointerDownEvent event) {
_pointerToKind[event.pointer] = event.kind;
if (isPointerAllowed(event)) {
addAllowedPointer(event);
} else {
handleNonAllowedPointer(event);
}
}
再看 addAllowedPointer,不同的GestureDetector 实现方式不一样,但是归根结底都会调用到GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform)
less
@override
@protected
void addAllowedPointer(PointerDownEvent event) {
startTrackingPointer(event.pointer, event.transform);
}
arduino
@protected
void startTrackingPointer(int pointer, [Matrix4? transform]) {
GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform);
...
}
注册handleEvent到pointerRouter,以接收后续的事件。