第1节:点击测试

1. 命中测试的起点

一个对象是否可以响应事件,取决于在其对命中测试过程中是否被添加到了 HitTestResult 列表 ,如果没有被添加进去,则后续的事件分发将不会分发给自己。下面我们看一下命中测试的过程:当发生用户事件时,Flutter 会从根节点(RenderView)开始调用它hitTest()

@override
void hitTest(HitTestResult result, Offset position) {
  //从根节点开始进行命中测试
  renderView.hitTest(result, position: position); 
  // 会调用 GestureBinding 中的 hitTest()方法,我们将在下一节中介绍。
  super.hitTest(result, position); 
}

第一步: renderView 是 RenderView 对应的 RenderObject 对象, RenderObject 对象的 hitTest 方法主要功能是:从该节点出发,按照深度优先的顺序递归遍历子树(渲染树)上的每一个节点并对它们进行命中测试。这个过程称为“渲染树命中测试”。

第二步:渲染树命中测试完毕后,会调用 GestureBinding 的 hitTest 方法,该方法主要用于处理手势。

2.渲染树命中测试过程

渲染树的命中测试流程就是父节点 hitTest 方法中不断调用子节点 hitTest 方法的递归过程。下面是RenderViewhitTest()源码:

// 发起命中测试,position 为事件触发的坐标(如果有的话)。
bool hitTest(HitTestResult result, { Offset position }) {
  if (child != null)
    child.hitTest(result, position: position); //递归对子树进行命中测试
  //根节点会始终被添加到HitTestResult列表中
  result.add(HitTestEntry(this)); 
  return true;
}

因为 RenderView 只有一个孩子,所以直接调用child.hitTest 即可。如果一个渲染对象有多个子节点,则命中测试逻辑为:如果任意一个子节点通过了命中测试或者当前节点“强行声明”自己通过了命中测试,则当前节点会通过命中测试。

results matching ""

    No results matching ""