Flutter ListView is very easy to use, and very versatile. As an Android developer used to creating Adapters for my RecyclerViews, I appreciate the simplicity of Flutter. However, one often used functionality is lacking, and it is smoothScrollToPosition(int position).
There is currently an open github issue requesting this very feature.
In the meanwhile, for lists where all items have the same height, there is a trick you can use.
Scroll to position for Flutter lists where all items have the same height
To follow the code tutorial, create a new app as follows.
1 |
flutter create listviewexample |
If you’re unsure how to set up a Flutter app, check out Getting started with Flutter official tutorial.
In main.dart, we launch the app as below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import 'package:flutter/material.dart'; import 'list/list_view.dart'; void main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: 'List View Example', theme: new ThemeData( primaryColor: const Color(0xFF43a047), accentColor: const Color(0xFFffcc00), primaryColorBrightness: Brightness.dark, ), home: new ListPage(), ); } } |
This won’t build until we create ListPage. So let’s create a new folder list in lib folder, and add the file list_view.dart to it.
ListPage widget
Firstly, we set up the ListPage widget, which consists of 2 buttons at the top, and a list of items below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
import 'package:flutter/material.dart'; const double _ITEM_HEIGHT = 70.0; class ListPage extends StatefulWidget { ListPage({Key key}) : super(key: key); @override _ListPageState createState() => new _ListPageState(); } class _ListPageState extends State<ListPage> { List<Item> _items; @override void initState() { super.initState(); // TODO - this is shortcut to specify items. // In a real app, you would get them // from your data repository or similar. _items = new List<Item>(); _items.add(new Item("Apples")); _items.add(new Item("Oranges")); _items.add(new Item("Rosemary")); _items.add(new Item("Carrots")); _items.add(new Item("Potatoes")); _items.add(new Item("Mushrooms")); _items.add(new Item("Thyme")); _items.add(new Item("Tomatoes")); _items.add(new Item("Peppers")); _items.add(new Item("Salt")); _items.add(new Item("Ground ginger")); _items.add(new Item("Cucumber")); } @override Widget build(BuildContext context) { Widget buttonsWidget = new Container( child: new Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ new FlatButton( textColor: Colors.blueGrey, color: Colors.white, child: new Text('SELECT ORANGES'), onPressed: _scrollToOranges, ), new FlatButton( textColor: Colors.blueGrey, color: Colors.white, child: new Text('SELECT TOMATOES'), onPressed: _scrollToTomatoes, ), ], ), ); Widget itemsWidget = new ListView( scrollDirection: Axis.vertical, shrinkWrap: true, children: _items.map((Item item) { return _singleItemDisplay(item); }).toList()); return new Scaffold( appBar: new AppBar( title: new Text("List of items"), ), body: new Padding( padding: new EdgeInsets.symmetric(vertical: 0.0, horizontal: 4.0), child: new Column(children: <Widget>[ buttonsWidget, new Expanded( child: itemsWidget,), ], ), ), ); } Widget _singleItemDisplay(Item item) { return new Container( height: _ITEM_HEIGHT, child: new Container ( padding: const EdgeInsets.all(2.0), color: new Color(0x33000000), child: new Text(item.displayName), ), ); } void _scrollToOranges() { // TODO } void _scrollToTomatoes() { // TODO } } class Item { final String displayName; const Item(this.displayName); } |
Now, you can run the app to view the list and the 2 buttons above it.
Scroll Controller
Secondly, we create a ScrollController…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
ScrollController _scrollController; @override void initState() { super.initState(); _scrollController = new ScrollController(); // TODO - this is shortcut to specify items. // In a real app, you would get them // from your data repository or similar. _items = new List<Item>(); _items.add(new Item("Apples")); _items.add(new Item("Oranges")); _items.add(new Item("Rosemary")); _items.add(new Item("Carrots")); _items.add(new Item("Potatoes")); _items.add(new Item("Mushrooms")); _items.add(new Item("Thyme")); _items.add(new Item("Tomatoes")); _items.add(new Item("Peppers")); _items.add(new Item("Salt")); _items.add(new Item("Ground ginger")); _items.add(new Item("Cucumber")); } |
… and add it to the itemsWidget.
1 2 3 4 5 6 7 8 |
Widget itemsWidget = new ListView( scrollDirection: Axis.vertical, shrinkWrap: true, controller: _scrollController, children: _items.map((Item item) { return _singleItemDisplay(item); }).toList()); |
Selected Item
Thirdly, to implement the scrolling functionality, we are going to add a selected property to Item…
1 2 3 4 5 6 |
class Item { final String displayName; bool selected; Item(this.displayName, this.selected); } |
… and update the items in initState()…
1 2 3 4 5 6 7 8 9 10 11 12 |
_items.add(new Item("Apples", false)); _items.add(new Item("Oranges", false)); _items.add(new Item("Rosemary", false)); _items.add(new Item("Carrots", false)); _items.add(new Item("Potatoes", false)); _items.add(new Item("Mushrooms", false)); _items.add(new Item("Thyme", false)); _items.add(new Item("Tomatoes", false)); _items.add(new Item("Peppers", false)); _items.add(new Item("Salt", false)); _items.add(new Item("Ground ginger", false)); _items.add(new Item("Cucumber", false)); |
Scroll to selected item
Fourthly, when building the Widget, it will scroll to the first found selected item. Add this to build(BuildContext context).
1 2 3 4 5 6 7 8 9 |
// Scroll to first selected item for (int i = 0; i < _items.length; i++) { if (_items.elementAt(i).selected) { _scrollController.animateTo(i * _ITEM_HEIGHT, duration: new Duration(seconds: 2), curve: Curves.ease); break; } } return new Scaffold(/... |
Buttons
Finally, let’s wire our 2 buttons.
1 2 3 4 5 6 7 8 9 10 11 |
void _scrollToOranges() { setState(() { for (var item in _items) { if (item.displayName == "Oranges") { item.selected = true; } else { item.selected = false; } } }); } |
1 2 3 4 5 6 7 8 9 10 11 |
void _scrollToTomatoes() { setState(() { for (var item in _items) { if (item.displayName == "Tomatoes") { item.selected = true; } else { item.selected = false; } } }); } |
Voila!
We can now scroll to a specific item when a Flutter ListView has a fixed height.
What next?
Subscribe to the open github issue requesting a method to programmatically scroll a Flutter ListView to a given position.

Mobile app developer with 12 years experience. Started with the Android SDK in 2010 and switched to Flutter in 2017. Past apps range from start ups to large tech (Google) and non tech (British Airways) companies, in various sectors (transport, commercial operations, e-commerce).
Great example. I just modeled my attempt at a similar app after it. Thanks.
how to scroll to specific item when each item in ListView have different size of height?
Hi friendss I am creating a drop-down menu button which contain more than 100 list of words instead of typing code is there any way to import this 100 list of data by using JSON file or some other…..
Great example. I just modeled my attempt at a similar app after it. Thanks.