— Flutter, Flutter Tips, Widgets — 1 min read
When you're working on a Flutter project you'll probably be using ListViews and at some point you might want to monitor scrolling events so you can add pagination or lazy loading if you're fetching data in some way. This post quickly runs through how to listen to scrolling events from a ListView using ScrollController.
ScrollController
is a class in Flutter that's made to - you guessed it - control a widget that scrolls. It's the same sort of concept as TabController
or TextEditingController
. It can be used to monitor scrolling events or jump to a certain position in a list. To kick things off first you'll need to create an instance of ScrollController
:
1ScrollController _controller = ScrollController();
Keep in mind this assumes you're going to use it with a ListView
widget, and everything is inside the State
portion of a StatefulWidget
. You're also going to need to create a void
to call when new events are received:
1void _onScrollEvent() {2 final extentAfter = _controller.position.extentAfter;3 print("Extent after: $extentAfter");4}
The method above is going to check position
(specifically extentAfter) and print the current value to the console. The extentAfter
value is essentially how many pixels or points there are left until you hit the bottom of the list, so this value should be zero once you reach the end of the last item in the list.
Now you just need to hook up the controller to the _onScrollEvent
method, you can do this in initState
and dispose
:
1@override2void initState() {3 _controller.addListener(_onScrollEvent);4 super.initState();5}6
7@override8void dispose() {9 _controller.removeListener(_onScrollEvent);10 super.dispose();11}
All that's left to do now is wire up the ScrollController
to your ListView
widget. Here's what the build
method of my widget looks like for this example:
1@override2Widget build(BuildContext context) {3 return ListView.builder(4 controller: _controller,5 itemCount: 50,6 itemBuilder: (context, index) {7 return ListTile(8 title: Text('List Item ${index + 1}')9 );10 }11 );12}
So all you really need to do is specify _controller
for the controller
prop. And that's all there is to it. If you're trying to implement lazy loading you could load your new items after extentAfter
reaches a certain point, for example 200 pixels:
1void _onScrollEvent() {2 final extentAfter = _controller.position.extentAfter;3 print("Extent after: $extentAfter");4 if (extentAfter < 300) {5 // Load new items6 }7}
There's also other values you can look at like extentBefore
for example, which is basically the opposite of extentAfter
. If you want to see a full example you can check it out in DartPad here.