handleGridObserve static method

GridViewObserveModel? handleGridObserve({
  1. required BuildContext context,
  2. double fetchLeadingOffset()?,
  3. double? customOverlap(
    1. BuildContext
    )?,
  4. double toNextOverPercent = 1,
})

Handles observation logic of a sliver similar to SliverGrid.

Implementation

static GridViewObserveModel? handleGridObserve({
  required BuildContext context,
  double Function()? fetchLeadingOffset,
  double? Function(BuildContext)? customOverlap,
  double toNextOverPercent = 1,
}) {
  final _obj = ObserverUtils.findRenderObject(context);
  if (_obj is! RenderSliverMultiBoxAdaptor) return null;
  final viewport = ObserverUtils.findViewport(_obj);
  if (viewport == null) return null;
  if (kDebugMode) {
    if (viewport.debugNeedsPaint) return null;
  }
  // The geometry.visible is not absolutely reliable.
  if (!(_obj.geometry?.visible ?? false) ||
      _obj.constraints.remainingPaintExtent < 1e-10) {
    return GridViewObserveModel(
      sliverGrid: _obj,
      viewport: viewport,
      visible: false,
      firstGroupChildList: [],
      displayingChildModelList: [],
    );
  }
  final scrollDirection = _obj.constraints.axis;
  var firstChild = _obj.firstChild;
  if (firstChild == null) return null;

  final offset = fetchLeadingOffset?.call() ?? 0;
  final overlap = customOverlap?.call(context) ?? _obj.constraints.overlap;
  final rawScrollViewOffset = _obj.constraints.scrollOffset + overlap;
  var scrollViewOffset = rawScrollViewOffset + offset;

  // Find out the first child which is displaying
  var targetFirstChild = firstChild;
  var lastFirstGroupChildWidget = targetFirstChild;

  while (!ObserverUtils.isBelowOffsetWidgetInSliver(
    scrollViewOffset: scrollViewOffset,
    scrollDirection: scrollDirection,
    targetChild: targetFirstChild,
    toNextOverPercent: toNextOverPercent,
  )) {
    /// Entering here means it is not the target object
    RenderBox? nextChild = _obj.childAfter(targetFirstChild);
    if (nextChild == null) break;
    targetFirstChild = nextChild;
  }
  if (targetFirstChild is! RenderIndexedSemantics) return null;
  lastFirstGroupChildWidget = targetFirstChild;

  final firstModel = GridViewObserveDisplayingChildModel(
    sliverGrid: _obj,
    viewport: viewport,
    index: targetFirstChild.index,
    renderObject: targetFirstChild,
  );
  List<GridViewObserveDisplayingChildModel> firstGroupChildModelList = [];
  firstGroupChildModelList.add(firstModel);

  final showingChildrenMaxOffset =
      rawScrollViewOffset + _obj.constraints.remainingPaintExtent - overlap;

  // Find out other child those have reached the specified offset.
  RenderBox? targetChild = _obj.childAfter(targetFirstChild);
  while (targetChild != null) {
    if (ObserverUtils.isReachOffsetWidgetInSliver(
      scrollViewOffset: max(scrollViewOffset, firstModel.layoutOffset),
      scrollDirection: scrollDirection,
      targetChild: targetChild,
      toNextOverPercent: toNextOverPercent,
    )) {
      if (targetChild is! RenderIndexedSemantics) break;
      firstGroupChildModelList.add(GridViewObserveDisplayingChildModel(
        sliverGrid: _obj,
        viewport: viewport,
        index: targetChild.index,
        renderObject: targetChild,
      ));
      lastFirstGroupChildWidget = targetChild;
    }

    RenderBox? nextChild = _obj.childAfter(targetChild);
    if (nextChild == null) break;
    targetChild = nextChild;
  }

  List<GridViewObserveDisplayingChildModel> showingChildModelList =
      List.from(firstGroupChildModelList);

  // Find the remaining children that are being displayed
  var displayingChild = _obj.childAfter(lastFirstGroupChildWidget);
  while (displayingChild != null) {
    if (ObserverUtils.isDisplayingChildInSliver(
      targetChild: displayingChild,
      showingChildrenMaxOffset: showingChildrenMaxOffset,
      scrollViewOffset: scrollViewOffset,
      scrollDirection: scrollDirection,
      toNextOverPercent: toNextOverPercent,
    )) {
      if (displayingChild is! RenderIndexedSemantics) {
        continue;
      }
      showingChildModelList.add(GridViewObserveDisplayingChildModel(
        sliverGrid: _obj,
        viewport: viewport,
        index: displayingChild.index,
        renderObject: displayingChild,
      ));
    }
    displayingChild = _obj.childAfter(displayingChild);
  }

  return GridViewObserveModel(
    sliverGrid: _obj,
    viewport: viewport,
    visible: true,
    firstGroupChildList: firstGroupChildModelList,
    displayingChildModelList: showingChildModelList,
  );
}