handleEvent method

  1. @override
void handleEvent(
  1. PointerEvent event,
  2. covariant HitTestEntry<HitTestTarget> entry
)
override

Override this method to handle pointer events that hit this render object.

For RenderBox objects, the entry argument is a BoxHitTestEntry. From this object you can determine the PointerDownEvent's position in local coordinates. (This is useful because PointerEvent.position is in global coordinates.)

Implementations of this method should call debugHandleEvent as follows, so that they support debugPaintPointersEnabled:

class RenderFoo extends RenderBox {
  // ...

  @override
  void handleEvent(PointerEvent event, HitTestEntry entry) {
    assert(debugHandleEvent(event, entry));
    // ... handle the event ...
  }

  // ...
}

Implementation

@override
void handleEvent(PointerEvent event, HitTestEntry entry) {
  assert(debugHandleEvent(event, entry));
  assert(() {
    for (final RenderTapRegion region in _registeredRegions) {
      if (!region.enabled) {
        return false;
      }
    }
    return true;
  }(), 'A RenderTapRegion was registered when it was disabled.');

  if (event is! PointerDownEvent) {
    return;
  }

  if (_registeredRegions.isEmpty) {
    assert(_tapRegionDebug('Ignored tap event because no regions are registered.'));
    return;
  }

  final BoxHitTestResult? result = _cachedResults[entry];

  if (result == null) {
    assert(_tapRegionDebug('Ignored tap event because no surface descendants were hit.'));
    return;
  }

  // A child was hit, so we need to call onTapOutside for those regions or
  // groups of regions that were not hit.
  final Set<RenderTapRegion> hitRegions =
      _getRegionsHit(_registeredRegions, result.path).cast<RenderTapRegion>().toSet();
  assert(_tapRegionDebug('Tap event hit ${hitRegions.length} descendants.'));

  final Set<RenderTapRegion> insideRegions = <RenderTapRegion>{
    for (final RenderTapRegion region in hitRegions)
      if (region.groupId == null) region
      // Adding all grouped regions, so they act as a single region.
      else ..._groupIdToRegions[region.groupId]!,
  };
  // If they're not inside, then they're outside.
  final Set<RenderTapRegion> outsideRegions = _registeredRegions.difference(insideRegions);

  bool consumeOutsideTaps = false;
  for (final RenderTapRegion region in outsideRegions) {
    assert(_tapRegionDebug('Calling onTapOutside for $region'));
    if (region.consumeOutsideTaps) {
      assert(_tapRegionDebug('Stopping tap propagation for $region (and all of ${region.groupId})'));
      consumeOutsideTaps = true;
    }
    region.onTapOutside?.call(event);
  }
  for (final RenderTapRegion region in insideRegions) {
    assert(_tapRegionDebug('Calling onTapInside for $region'));
    region.onTapInside?.call(event);
  }

  // If any of the "outside" regions have consumeOutsideTaps set, then stop
  // the propagation of the event through the gesture recognizer by adding it
  // to the recognizer and immediately resolving it.
  if (consumeOutsideTaps) {
    GestureBinding.instance.gestureArena.add(event.pointer, _DummyTapRecognizer()).resolve(GestureDisposition.accepted);
  }
}