本文最后更新于 93 天前,其中的信息可能已经有所发展或是发生改变。
简单总结记录
GestureBinding:
1. handlePointerEvent 事件分发 -> _handlePointerEventImmediately
2. _handlePointerEventImmediately 对down/up,cancel等事件进行处理
2.1 pointerDown事件,会进行hittest命中测试 -> renderView.hitTest -> renderBox的hitTest
2.1.1 renderView是RenderObject树的根,从这里遍历整颗RenderTree,执行hitTest 即 renderBox的hitTest
2.1.2 renderbox这里有个关键的位置: hitTestChild || hitTestSelf,意味着child先被命中测试就直接返回结束
2.2 hitTest返回True后,将其添加到hitTestResult内,以供后续的事件分发处理
entry.target.handleEvent() => RenderObject 默认有实现HitTestTarget,但是个空实现,只有需要处理事件的render才会实现
3. dispatchEvent
3.1 没有命中的 ==》 pointerRouter.route(event); 这里在GestureDetector部分查看
3.2 for (final HitTestEntry entry in hitTestResult.path) 遍历进行 处理事件
4. 总结
当设备触发point事件时,参与分发的binding有RenderBinding和GestureBinding,RenderView是RenderTree分发的总入口
当事件为point down时,开始执行hitTest()测试,把符合条件的RenderObject加入到hitTestResult中
如果是其他事件,就根据point id 取出之前的hitTestResult并分发
最后就是遍历hitTestResult,执行 entry.target.handleEvent();
GestureDetector -> RawGestureDetectorState -> Listener
事件冲突 - 手势竞技场
1. handleEvent内,主要 四个方法
1.1 分发event pointerRouter.route(event);
1.2 pointDownEvent => gestureArena.close(event.pointer);
1.3 PointerUpEvent => gestureArena.sweep(event.pointer);
1.4 PointerSignalEvent => pointerSignalResolver.resolve(event);
2. close方法 - down事件停止新的成员进行竞技场
2.1 有个关注点:eagerWinner激进的竞争者 直接 acceptGesture
3. sweep方法 -
Listener内对相关HitTestBehavior设置
# 如果Behavior是opaque,且子类没有重写hitTestSelf,则自己加入到事件消费的行列
# behavior == HitTestBehavior.translucent 同上
# _handlePointerDown方法 -> -> -> addAllowedPointer -> startTrackingPointer
即GestureDetector内使用各种手势识别时 GestureDetector会将其添加到手势竞技场
GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform); event分发
Container其实是个StateLessWidget,它本身并没有RenderObject对应,可以理解为是个配置项,真实渲染的render是其他配置引进的,比如color对应的ColoredBox
所以Container设置任意背景色,可以响应点击事件
PointerRouter