verticalOffsetForBulkChange<T> static method
New vertical offset after a bulk list change (e.g. expandAll/collapseAll), anchoring to the top node — or its nearest surviving ancestor if it was removed. Null when no adjustment is needed.
Implementation
static double? verticalOffsetForBulkChange<T>({
required List<FlatNode<T>> oldList,
required List<FlatNode<T>> newList,
required double currentOffset,
required double itemExtent,
required double topPadding,
required double newContentHeight,
required double viewportHeight,
}) {
if (identical(oldList, newList)) return null;
if (oldList.isEmpty || newList.isEmpty) return null;
final topIndex = ((currentOffset - topPadding) / itemExtent)
.floor()
.clamp(0, oldList.length - 1);
var anchorPixelOffset =
currentOffset - (topPadding + topIndex * itemExtent);
int newIndex = -1;
for (int i = topIndex; i >= 0; i--) {
newIndex = newList.indexWhere((fn) => fn.node.id == oldList[i].node.id);
if (newIndex >= 0) {
if (i != topIndex) anchorPixelOffset = 0.0;
break;
}
}
if (newIndex < 0) return null;
final targetOffset = topPadding + newIndex * itemExtent + anchorPixelOffset;
final newMaxExtent =
(newContentHeight - viewportHeight).clamp(0.0, double.infinity);
final clamped = targetOffset.clamp(0.0, newMaxExtent);
return (clamped - currentOffset).abs() > 0.5 ? clamped : null;
}