animateToPage method
void
animateToPage(})
Animates smoothly to the specified page index.
Note that animation is ignored when duration is zero, and the page
index is not checked to be within the range of the scroll view's pages.
Example
final controller = PageController();
controller.animateToPage(
2,
duration: const Duration(milliseconds: 500),
curve: Curves.easeIn,
);
Implementation
void animateToPage(
int page, {
Duration duration = const Duration(milliseconds: 300),
Curves curve = Curves.easeInOut,
}) {
if (_attachedElement == null) return;
final isHoriz = direction == ScrollDirection.horizontal;
// calculate page size
final pageSize =
(isHoriz
? _attachedElement!.clientWidth
: _attachedElement!.clientHeight) *
viewportFraction;
// calculate target scroll offset
final targetOffset = page * pageSize;
// jump immediately if duration is zero or the user prefers less motion
if (duration == Duration.zero ||
window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
jumpToPage(page);
return;
}
// calculate starting offset and change
final startOffset = isHoriz
? _attachedElement!.scrollLeft
: _attachedElement!.scrollTop;
// calculate change in scroll offset
final change = targetOffset - startOffset;
// setup animation variables
final startTime = DateTime.now().millisecondsSinceEpoch;
final totalDurationMs = duration.inMilliseconds;
final element = _attachedElement!;
// a newer animation takes over from this one
final animation = ++_animation;
void step() {
if (_attachedElement == null || animation != _animation) return;
// scroll snapping would pull every frame back to the nearest page, and
// a rebuild clears attributes it did not set, so this is set every frame
element.setAttribute(_animatingAttribute, '');
// calculate animation progress
final elapsed = DateTime.now().millisecondsSinceEpoch - startTime;
final progress = (elapsed / totalDurationMs).clamp(0.0, 1.0);
// calculate easing progress
final easedProgress = curve.build(progress);
// calculate current scroll position
final current = startOffset + change * easedProgress;
// update scroll position
if (isHoriz) {
_attachedElement!.scrollLeft = current;
} else {
_attachedElement!.scrollTop = current;
}
// notify listeners of scroll position changes
notifyListeners();
// continue animation if not done
if (progress < 1.0) {
onComponentRendered(step);
} else {
element.removeAttribute(_animatingAttribute);
}
}
// start animation
step();
}