Flutter ScrollablePositionedList: Scroll to a position in listview

Nabil Mosharraf Hossain
2 min readMay 3, 2020

--

Photo by Glenn Carstens-Peters on Unsplash

Consider this User Story: Your user is reading a posts in a long list of posts. You want to ensure that the user’s position is saved when he gets back. And he can return to that position when he returns. I will share the ways we can do this features.

Old Aproach: Using ScrollController and ScrollNotification

new NotificationListener<ScrollUpdateNotification>(
child: new ListView(
controller: _scrollController,
children: ...
),
onNotification: (t) {
if (t is ScrollEndNotification) {
print(_scrollController.position.pixels);
}
},
),

Here we are listener to the position using NotificationListener. Also we can use _scrollController to control the Listview position. However we have to initialise the _scrollController in initState and listen to scroll position listeners. A more elegant solution is ScrollablePositionedList

A ScrollablePositionedList works much like the builder version of ListView except that the list can be scrolled or jumped to a specific item.

Example

A ScrollablePositionedList can be created with:

final ItemScrollController itemScrollController = ItemScrollController();
final ItemPositionsListener itemPositionsListener = ItemPositionsListener.create();
ScrollablePositionedList.builder(
itemCount: 500,
itemBuilder: (context, index) => Text('Item $index'),
itemScrollController: itemScrollController,
itemPositionsListener: itemPositionsListener,
);

One then can scroll to a particular item with:

itemScrollController.scrollTo(
index: 150,
duration: Duration(seconds: 2),
curve: Curves.easeInOutCubic);

or jump to a particular item with:

itemScrollController.jumpTo(index: 150);

So lets solve our User Story using above library:

Scroll to a position in the ListView when user visit the page again using initialScrollIndex. Here I have set the initialScrollIndex to 150

ScrollablePositionedList.builder(
itemCount: 500,
itemBuilder: (context, index) => Text('Item $index'),
initialScrollIndex: 150,
itemPositionsListener: itemPositionsListener,
);

Save the position of the listview when the user goes back. We will use builtin flutter widget WillPopScope. WillPopScope triggers a onWillPop the moment a user tries to go away from the present route. That is the place we will listen to the scroll position. Lets see this in code:

final ItemPositionsListener itemPositionsListener = ItemPositionsListener.create();@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
//save the last seen position
position = itemPositionsListener.itemPositions.value.first.index

//trigger leaving and use own data
Navigator.pop(context, false);
//we need to return a future
return Future.value(false);
},
child: ScrollablePositionedList.builder(
initialScrollIndex: 150,
itemPositionsListener: itemPositionsListener,
itemCount: 500,
itemBuilder: (context, index) => Text('Item $index'),
);

So using the itemPositionListener that has been attached we get the list of visible positions of the listview. We get only the first visible item from that listener.

See the whole code in gist

Thats it from me now. Thanks

--

--