Scroll to top ListView flutter

Flutter ListViewis very easy to use, and very versatile. As an Android developer used to creating Adaptersfor 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.

create new app
1
flutter create listviewexample

If youre unsure how to set up a Flutter app, check outGetting started with Flutterofficial tutorial.

In main.dart, we launch the app as below.

main.dart
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 wont build until we create ListPage. So lets create a new folder list in lib folder, and add the file list_view.dartto it.

Looking for a Flutter job?

Check out my job board dedicated to Flutter at flutterjobs.info

ListPage widget

Firstly, we set up the ListPage widget, which consists of 2 buttons at the top, and a list of items below.

list/list_view.dart
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

initState()
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.

build(BuildContext context)/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

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()

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 tobuild(BuildContext context).

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, lets wire our 2 buttons.

_scrollToOranges()
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;
}
}
});
}
_scrollToTomatoes
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.

Scroll to top ListView flutter

What next?

Subscribe to the open github issue requesting a method to programmatically scroll a Flutter ListView to a given position.

Check out Being a software developer in 2020!
Scroll to top ListView flutter
Natalie Masse Hooper

Related

Author: Natalie Masse Hooper

Mobile app developer. 11 years experience with the Android SDK, 4 years with Flutter. Past apps range from start ups to large tech (Google) and non tech (British Airways) companies.LinkedInnatalie ( at ) cogitas (dot) net View all posts by Natalie Masse Hooper