Flutter: Scrolling to a widget in ListView Flutter: Scrolling to a widget in ListView dart dart

Flutter: Scrolling to a widget in ListView


By far, the easiest solution is to use Scrollable.ensureVisible(context). As it does everything for you and work with any widget size. Fetching the context using GlobalKey.

The problem is that ListView won't render non-visible items. Meaning that your target most likely will not be built at all. Which means your target will have no context ; preventing you from using that method without some more work.

In the end, the easiest solution will be to replace your ListView by a SingleChildScrollView and wrap your children into a Column. Example :

class ScrollView extends StatelessWidget {  final dataKey = new GlobalKey();  @override  Widget build(BuildContext context) {    return new Scaffold(      primary: true,      appBar: new AppBar(        title: const Text('Home'),      ),      body: new SingleChildScrollView(        child: new Column(          children: <Widget>[            new SizedBox(height: 160.0, width: double.infinity, child: new Card()),            new SizedBox(height: 160.0, width: double.infinity, child: new Card()),            new SizedBox(height: 160.0, width: double.infinity, child: new Card()),            // destination            new Card(              key: dataKey,              child: new Text("data\n\n\n\n\n\ndata"),            )          ],        ),      ),      bottomNavigationBar: new RaisedButton(        onPressed: () => Scrollable.ensureVisible(dataKey.currentContext),        child: new Text("Scroll to data"),      ),    );  }}

NOTE : While this allows to scroll to the desired item easily, consider this method only for small predefined lists. As for bigger lists you'll get performance problems.

But it's possible to make Scrollable.ensureVisible work with ListView ; although it will require more work.


Unfortunately, ListView has no built-in approach to a scrollToIndex() function. You’ll have to develop your own way to measure to that element’s offset for animateTo() or jumpTo(), or you can search through these suggested solutions/plugins or from other posts like flutter ListView scroll to index not available

(the general scrollToIndex issue is discussed at flutter/issues/12319 since 2017, but still with no current plans)


But there is a different kind of ListView that does support scrollToIndex:

You set it up exactly like ListView and works the same, except you now have access to a ItemScrollController that does:

  • jumpTo({index, alignment})
  • scrollTo({index, alignment, duration, curve})

Simplified example:

ItemScrollController _scrollController = ItemScrollController();ScrollablePositionedList.builder(  itemScrollController: _scrollController,  itemCount: _myList.length,  itemBuilder: (context, index) {    return _myList[index];  },)_scrollController.scrollTo(index: 150, duration: Duration(seconds: 1));

(note that this library is developed by Google but not by the core Flutter team.)


If your widgets inside the ListView all have the same height, you can implement it like this:

Screenshot:

enter image description here


For ListView, you can try this, the following code will animate to 10th index.

class HomePage extends StatelessWidget {  final _controller = ScrollController();  final _height = 100.0;  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(),      floatingActionButton: FloatingActionButton(        onPressed: () => _animateToIndex(10),        child: Icon(Icons.arrow_downward),      ),      body: ListView.builder(        controller: _controller,        itemCount: 100,        itemBuilder: (_, i) => Container(          height: _height,          child: Card(child: Center(child: Text("Item $i"))),        ),      ),    );  }  _animateToIndex(i) => _controller.animateTo(_height * i, duration: Duration(seconds: 2), curve: Curves.fastOutSlowIn);}