animateScrollToKey method
Future<bool>
animateScrollToKey(
- TKey key, {
- required ScrollController scrollController,
- Duration duration = const Duration(milliseconds: 300),
- Curve curve = Curves.easeInOut,
- double alignment = 0.0,
- AncestorExpansionMode ancestorExpansion = AncestorExpansionMode.immediate,
- double extentEstimator(
- TKey key
- double sliverBaseOffset = 0.0,
Animates scrollController to reveal key. See
TreeController.animateScrollToKey for the full contract.
Implementation
Future<bool> animateScrollToKey(
TKey key, {
required ScrollController scrollController,
Duration duration = const Duration(milliseconds: 300),
Curve curve = Curves.easeInOut,
double alignment = 0.0,
AncestorExpansionMode ancestorExpansion = AncestorExpansionMode.immediate,
double Function(TKey key)? extentEstimator,
double sliverBaseOffset = 0.0,
}) async {
assert(
alignment >= 0.0 && alignment <= 1.0,
"alignment must be between 0.0 and 1.0",
);
if (!scrollController.hasClients) return false;
// Collect any ancestors that are currently collapsed.
final collapsedAncestors = <TKey>[];
{
TKey? current = _controller.getParent(key);
while (current != null) {
if (!_controller.isExpanded(current)) collapsedAncestors.add(current);
current = _controller.getParent(current);
}
}
// Animated concurrent expand+scroll. Falls back to the standard path
// when there's nothing to expand or when animations are disabled.
if (ancestorExpansion == AncestorExpansionMode.animated &&
collapsedAncestors.isNotEmpty &&
_controller.animationDuration != Duration.zero &&
duration != Duration.zero) {
return _animatedConcurrentScroll(
key: key,
ancestors: collapsedAncestors,
scrollController: scrollController,
duration: duration,
curve: curve,
alignment: alignment,
extentEstimator: extentEstimator,
sliverBaseOffset: sliverBaseOffset,
);
}
if (ancestorExpansion == AncestorExpansionMode.none &&
collapsedAncestors.isNotEmpty) {
return false;
}
if (collapsedAncestors.isNotEmpty) {
ensureAncestorsExpanded(key);
}
final sliverOffset = scrollOffsetOf(key, extentEstimator: extentEstimator);
if (sliverOffset == null) return false;
final position = scrollController.position;
final viewportExtent = position.viewportDimension;
final rowExtent = extentOf(key, extentEstimator: extentEstimator);
final rawTarget =
sliverBaseOffset +
sliverOffset -
(viewportExtent - rowExtent) * alignment;
final clamped = rawTarget.clamp(
position.minScrollExtent,
position.maxScrollExtent,
);
if (duration == Duration.zero) {
position.jumpTo(clamped);
} else {
await position.animateTo(clamped, duration: duration, curve: curve);
}
return true;
}