Can a scrollController.animateTo be cancelled or interrupted in the middle of its scroll?
For example, lets say I have a listview
and I want to animateTo
the bottom over the course of 10 seconds:
_scrollController.animateTo
(
_scrollController.position.maxScrollExtent,
duration: Duration(seconds: 10),
curve: Curves.linear
);
But 5 seconds into this, some event occurs, say a state change, so I want to immediately cancel the scroll wherever it happens to be. Is this possible?
I'm not sure if there is a better solution but this seems to work.
You can call animateTo
again, except with the current position as the destination, and 0 seconds as the duration.
You can try with this demo below:
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
home: ScrollDemoWidget(),
),
);
}
class ScrollDemoWidget extends StatefulWidget {
const ScrollDemoWidget({Key? key}) : super(key: key);
@override
_ScrollDemoWidgetState createState() => _ScrollDemoWidgetState();
}
class _ScrollDemoWidgetState extends State<ScrollDemoWidget> {
final ScrollController _scrollController = ScrollController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Scroll Demo'),
actions: [
IconButton(
icon: const Icon(Icons.arrow_upward),
onPressed: () {
double current = _scrollController.position.pixels;
double extent = _scrollController.position.maxScrollExtent;
double millis = 10 * 1000 * (current / extent);
_scrollController.animateTo(0,
duration: Duration(milliseconds: millis.round()),
curve: Curves.linear);
},
),
IconButton(
icon: const Icon(Icons.arrow_downward),
onPressed: () {
double current = _scrollController.position.pixels;
double extent = _scrollController.position.maxScrollExtent;
double millis = 10 * 1000 * (1 - (current / extent));
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: millis.round()),
curve: Curves.linear);
},
),
IconButton(
icon: const Icon(Icons.stop),
onPressed: () {
_scrollController.animateTo(_scrollController.position.pixels,
duration: const Duration(seconds: 0), curve: Curves.linear);
},
),
],
),
body: ListView.builder(
controller: _scrollController,
itemCount: 100,
itemBuilder: (context, i) => ListTile(title: Text('Tile $i')),
),
);
}
}