I have a scrollable ListView
where the number of items can change dynamically. Whenever a new item is added to the end of the list, I would like to programmatically scroll the ListView
to the end. (e.g., something like a chat message list where new messages can be added at the end)
My guess is that I would need to create a ScrollController
in my State
object and pass it manually to the ListView
constructor, so I can later call animateTo()
/ jumpTo()
method on the controller. However, since I cannot easily determine the maximum scroll offset, it seems impossible to simply perform a scrollToEnd()
type of operation (whereas I can easily pass 0.0
to make it scroll to the initial position).
Is there an easy way to achieve this?
Using reverse: true
is not a perfect solution for me, because I would like the items to be aligned at the top when there are only a small number of items that fit within the ListView
viewport.
Use ScrollController.jumpTo()
or ScrollController.animateTo()
method to achieve this.
Example:
final _controller = ScrollController();
@override
Widget build(BuildContext context) {
// After 1 second, it takes you to the bottom of the ListView
Timer(
Duration(seconds: 1),
() => _controller.jumpTo(_controller.position.maxScrollExtent),
);
return ListView.builder(
controller: _controller,
itemCount: 50,
itemBuilder: (_, __) => ListTile(title: Text('ListTile')),
);
}
If you want smooth scrolling, then instead of using jumpTo
above use
_controller.animateTo(
_controller.position.maxScrollExtent,
duration: Duration(seconds: 1),
curve: Curves.fastOutSlowIn,
);