第一部分 手势组件的基本关系
1 我们一般使用 GestureDetector ,GestureDetector 最终build的是RawGestureDetector
GestureDetector -> RawGestureDetector
2 RawGestureDetector 中的gestures就是我们注册的手势。
3 RawGestureDetector 最终build的是Listener()
4 Listener.createRenderObject 最终返回的是 RenderPointerListener
一个可以处理手指事件的RenderObject。
5 在Listener的 onPointerDown : _handlePointerDown 会调中将gestures 与 事件关联。
第二部分 手势的基本传递
1 从 GestureBinding的 _handlePointerEvent 方法开始,_handlePointerEvent方法里面主要包括两个方法的调用 hitTest 和 dispatchEvent
2 hitTest的作用主要是返回一个HitTestResult,HitTestResult里面包含一个`List<HitTestEntry>` 是用于分发和竞争事件的,而每个 `HitTestEntry.target` 都会存储每个控件的 `RenderObject` 。
3 hitTest的实现主要在 RendererBinding.hitTest 与 `GestureBinding.hitTest`根据with的先后顺序,先执行 `RendererBinding.hitTest`,再执行 `GestureBinding.hitTest`.hitTest自下而上的得到了一个 `HitTestResult` 的相应控件列表了,最底下的 Child 在最上面.
4 GestureBinding.dispatchEvent 做事件分发,遍历调用entry.target.handleEvent(),事实上并不是所有的控件的 `RenderObject` 子类都会处理 `handleEvent` ,大部分时候,只有带有 `RenderPointerListener` (RenderObject) / `Listener` (Widget) 的才会处理 `handleEvent` 事件,并且从上述源码可以看出,handleEvent 的执行是不会被拦截打断的。
从这里就跟第一部分的内容关联上了。
第三部分 _handlePointerDown->addPointer->addAllowedPointer
在addAllowPointer中,虽然不同的recognizer实现不一样,但是都会把自己加入到竞技场。
void _handlePointerDown(PointerDownEvent event) {
assert(_recognizers != null);
for (final GestureRecognizer recognizer in _recognizers!.values) {
recognizer.addPointer(event);
}
}
void addPointer(PointerDownEvent event) {
_pointerToKind[event.pointer] = event.kind;
if (isPointerAllowed(event)) {
addAllowedPointer(event);
} else {
handleNonAllowedPointer(event);
}
}
加入竞技场,竞技场在GestureBinding中维护.
GestureBinding.instance.gestureArena.add(event.pointer, this)
GestureArenaEntry add(int pointer, GestureArenaMember member) {
//创建pointer对应的竞技场,member就是regcognizder。每个member都会被封窗成GestureAernaEbtry.
final _GestureArena state = _arenas.putIfAbsent(pointer, () {
assert(_debugLogDiagnostic(pointer, '★ Opening new gesture arena.'));
return _GestureArena();
});
state.add(member);
assert(_debugLogDiagnostic(pointer, 'Adding: $member'));
return GestureArenaEntry._(this, pointer, member);
}