hitTest method

  1. @override
bool hitTest(
  1. HitTestResult result, {
  2. required double localX,
  3. required double localY,
})
override

Performs hit-testing at (localX, localY) in this object's coordinate space. Adds matching entries to result, deepest first.

Returns true if this object or a descendant was hit.

Implementation

@override
bool hitTest(
  HitTestResult result, {
  required double localX,
  required double localY,
}) {
  if (localX < 0 ||
      localY < 0 ||
      localX >= size.width ||
      localY >= size.height) {
    return false;
  }

  if (children.isEmpty) return false;

  final separatorBreaks = _separatorBreaks(separator);
  final offset = controller.offset.clamp(0, controller.maxOffset);
  final contentY = localY + offset;

  if (!variableHeight) {
    final stride = math.max(1, itemExtent).toInt() + separatorBreaks;
    final index = stride > 0 ? (contentY ~/ stride).toInt() : 0;
    if (index < 0 || index >= children.length) return false;
    final childTop = (index * stride).toInt();
    final childBottom = childTop + math.max(1, itemExtent).toInt();
    if (contentY < childTop || contentY >= childBottom) return false;
    final child = children[index];
    final childX = localX - child.offset.dx;
    final childY = contentY - childTop - child.offset.dy;
    return child.hitTest(result, localX: childX, localY: childY);
  }

  if (_lastPaintOffset == offset &&
      _lastPaintViewportHeight == size.height.round() &&
      _lastVisibleHits.isNotEmpty) {
    final bufferY = localY.toInt() + _lastOffsetInItem;
    for (final hit in _lastVisibleHits) {
      if (bufferY >= hit.bufferStart && bufferY < hit.bufferEnd) {
        final child = children[hit.index];
        final childX = localX - child.offset.dx;
        final childY = bufferY - hit.bufferStart - child.offset.dy;
        return child.hitTest(result, localX: childX, localY: childY);
      }
    }
  }

  // Variable-height hit testing favors correctness over speed.
  // Walk rows in order using measured heights where available.
  final estimate = math.max(1, estimatedItemExtent ?? itemExtent).toInt();
  _syncCache(children.length, separatorBreaks, estimate);
  var top = 0;
  for (var i = 0; i < children.length; i++) {
    final childHeight = _estimateHeight(i, estimate);
    final bottom = top + childHeight;
    if (contentY >= top && contentY < bottom) {
      final child = children[i];
      final childX = localX - child.offset.dx;
      final childY = contentY - top - child.offset.dy;
      return child.hitTest(result, localX: childX, localY: childY);
    }

    top = bottom;
    if (i < children.length - 1) {
      final sepBottom = top + separatorBreaks;
      if (contentY >= top && contentY < sepBottom) return false;
      top = sepBottom;
    }
  }
  return false;
}