estimateLayoutOffset method

  1. @override
_Measure estimateLayoutOffset(
  1. int buildIndex,
  2. int childCount,
  3. double? time,
  4. _MovingPopUpList? popUpList,
)
override

Implementation

@override
_Measure estimateLayoutOffset(int buildIndex, int childCount, double? time,
    _MovingPopUpList? popUpList) {
  assert(!intervalManager.hasPendingUpdates);
  assert(buildIndex >= 0 && buildIndex <= childCount);
  final list = listOf(popUpList)!;

  late int firstBuildIndex, lastBuildIndex /* exclueded */;
  late double size, scrollOffset;
  late int count, offset;
  late _Measure value;
  Iterable<_Interval>? ilist;
  var outside = false;
  if (buildIndex == 0) {
    value = _Measure.zero;
    time = null;
  } else if (buildIndex == childCount && popUpList == null) {
    value = _Measure(geometry!.scrollExtent);
  } else if (buildIndex < indexOf(list.firstChild!)) {
    // above
    final pd = parentDataOf(list.firstChild!)!;
    firstBuildIndex = 0;
    lastBuildIndex = pd.index!;
    scrollOffset = 0.0;
    size = pd.layoutOffset!;
    count = lastBuildIndex;
    offset = buildIndex;
    outside = true;
  } else if (buildIndex > indexOf(list.lastChild!)) {
    // bottom
    final lastParentData = parentDataOf(list.lastChild!)!;
    firstBuildIndex = lastParentData.index! + 1;
    scrollOffset =
        lastParentData.layoutOffset! + paintExtentOf(list.lastChild!);
    if (childCount == firstBuildIndex) {
      value = _Measure(scrollOffset);
    } else {
      lastBuildIndex = childCount;
      if (popUpList == null) {
        size = geometry!.scrollExtent - scrollOffset;
      } else {
        final firstParentData = parentDataOf(list.firstChild!)!;
        // For popups you can only estimate the size
        size = extrapolateMaxScrollOffset(
                popUpList,
                firstParentData.index!,
                lastParentData.index!,
                firstParentData.layoutOffset!,
                scrollOffset,
                childCount) -
            scrollOffset;
      }
      count = childCount - firstBuildIndex;
      offset = buildIndex - firstBuildIndex;
      outside = true;
    }
  } else {
    // inner
    var child = list.firstChild;
    while (child != null) {
      if (indexOf(child) == buildIndex) {
        value = parentDataOf(child)!.layoutOffset!.toExactMeasure();
        break;
      }
      child = childAfter(child);
    }
    assert(child != null);
  }
  if (outside) {
    ilist ??=
        (popUpList == null) ? intervalManager.list : popUpList.intervals;
    for (final i in ilist.expandedIntervals.whereType<_SpaceInterval>()) {
      final bi = i.actualBuildOffset;
      if (bi >= firstBuildIndex) {
        if (bi >= lastBuildIndex) break;
        final csz = i.currentSize;
        if (bi < buildIndex) {
          scrollOffset += csz;
          offset--;
        }
        count--;
        size -= csz;
      }
    }
    if (size < 0) size = 0;
    if (count > 0) scrollOffset += (offset * size) / count;
    value = _Measure(scrollOffset, true);
  }
  if (time != null) {
    var bi = 0, adjust = 0.0;
    ilist ??=
        (popUpList == null) ? intervalManager.list : popUpList.intervals;
    for (final i in ilist) {
      if (bi >= buildIndex) break;
      if (i is _AnimatedSpaceInterval) {
        adjust += i.futureSize(time) - i.currentSize;
      }
      bi += i.buildCount;
    }
    value += adjust.toExactMeasure();
  }
  if (popUpList != null) value += _Measure(popUpList.currentScrollOffset!);
  assert(value.value.isFinite);
  return value;
}