offsetsForScaleChange static method

({double? horizontal, double? vertical}) offsetsForScaleChange({
  1. required double currentVerticalOffset,
  2. required double oldItemExtent,
  3. required double newItemExtent,
  4. required double oldTopPadding,
  5. required double newTopPadding,
  6. required double newContentHeight,
  7. required double viewportHeight,
  8. required double? currentHorizontalOffset,
  9. required double oldContentWidth,
  10. required double newContentWidth,
  11. required double hMinScrollExtent,
  12. required double hMaxScrollExtent,
})

New vertical/horizontal offsets after a Scale change, preserving the node at the top of the viewport. A field is null when that axis needs no move.

Implementation

static ({double? vertical, double? horizontal}) offsetsForScaleChange({
  required double currentVerticalOffset,
  required double oldItemExtent,
  required double newItemExtent,
  required double oldTopPadding,
  required double newTopPadding,
  required double newContentHeight,
  required double viewportHeight,
  required double? currentHorizontalOffset,
  required double oldContentWidth,
  required double newContentWidth,
  required double hMinScrollExtent,
  required double hMaxScrollExtent,
}) {
  // Vertical: map the top fractional item position into the new item extent.
  final topFractionalIndex = oldItemExtent > 0
      ? (currentVerticalOffset - oldTopPadding) / oldItemExtent
      : 0.0;
  final newOffset = newTopPadding + topFractionalIndex * newItemExtent;
  final newMaxExtent =
      (newContentHeight - viewportHeight).clamp(0.0, double.infinity);
  final clampedV = newOffset.clamp(0.0, newMaxExtent);
  final double? vertical =
      (clampedV - currentVerticalOffset).abs() > 0.5 ? clampedV : null;

  // Horizontal: scale the offset by the content-width ratio.
  double? horizontal;
  if (currentHorizontalOffset != null && oldContentWidth > 0) {
    final ratio = newContentWidth / oldContentWidth;
    final newH = currentHorizontalOffset * ratio;
    final clampedH = newH.clamp(hMinScrollExtent, hMaxScrollExtent);
    if ((clampedH - currentHorizontalOffset).abs() > 0.5) {
      horizontal = clampedH;
    }
  }

  return (vertical: vertical, horizontal: horizontal);
}