In this article, we’ll take a look on how to build a ListView in Flutter. If you haven’t checked out my previous articles on Flutter, I highly recommend taking a look at them:
- 9 Points to consider before getting started with flutter.
- Getting started with flutter
- Flutter vs React Native (optional)
Just to give an overview, Flutter is Google’s mobile app SDK which helps in creating mobile applications for both iOS and Android devices using a single codebase. The apps developed using Flutter are not hybrid applications but cross-platform native apps which run as native apps on all devices. Flutter’s code actually compiles into Java Binaries which is also what happens when we develop native Android Apps using Java/Kotlin or in case of iOS, Swift.
Building a ListView in Flutter
Getting started
We’ll start by creating an empty project. Click on File -> New Flutter Project, and create a flutter application.
You’ll notice some code in the main.dart file, delete all of it. We’ll be creating a new app from scratch.
Let’s start by adding an external package that we will be using in the project. Expand the project folder in the left-hand project pane. You’ll find a file named pubspec.yaml, think of this as the gradle file for flutter. This is where you add your dependencies for flutter projects.
We’ll be adding a library to generate random words to display in our listview. Copy and paste the code below.
english_words: ^3.1.0
This is how your pubspec.yaml might look like:
name: flutter_list description: A new Flutter application. dependencies: flutter: sdk: flutter # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.0 english_words: ^3.1.0 dev_dependencies: flutter_test: sdk: flutter # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec # The following section is specific to Flutter. flutter: # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.io/assets-and-images/#resolution-aware. # For details regarding adding assets from package dependencies, see # https://flutter.io/assets-and-images/#from-packages # To add custom fonts to your application, add a fonts section here, # in this "flutter" section. Each entry in this list should have a # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: # fonts: # - family: Schyler # fonts: # - asset: fonts/Schyler-Regular.ttf # - asset: fonts/Schyler-Italic.ttf # style: italic # - family: Trajan Pro # fonts: # - asset: fonts/TrajanPro.ttf # - asset: fonts/TrajanPro_Bold.ttf # weight: 700 # # For details regarding fonts from package dependencies, # see https://flutter.io/custom-fonts/#from-packages
Adding a stateless widget
I hope you’ve deleted all the code in main.dart file as we would be starting from scratch. First, we need to add a stateless widget, which can be thought of as the container of our app. This is the container that would never change. All the widgets added henceforth will be its children or grand-children and so on.
Import the material library and the library to generate random words.
import 'package:flutter/material.dart'; import 'package:english_words/english_words.dart';
Let’s initiate the app launch in the main method:
void main() => runApp(new MyApp());
Finally, we create the stateless widget MyApp as below:
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "List in Flutter", home: new Scaffold( appBar: new AppBar( title: Text("List"), ), body: RandomWords(), ), ); } }
To create a Stateless widget all you need to do is extend the StatelessWidget class and override build method. Build returns a Widget, in our case which is MaterialApp, as we are using material design.
Next, come the properties of the MaterialApp such as the title, it’s content (home), theme, locales etc., in our case we will be changing the title and adding a body to our material app.
For the home property, we return a Scaffold which is a container that lets us add material design elements such as Snackbars, sliding drawer, ActionBar etc. Using Scaffold, we will add an action bar to our app as shown above.
Next step is to build the body of the Scaffold.
Building the body
For the body of our app, we will be adding a ListView which will be a stateless widget. Although we won’t be interacting with the listview items right now, it is a good idea to make them stateful as in most use cases you would associate a click action on the list items.
Creating a stateful widget is as simple as extending the StatefulWidget class:
class RandomWords extends StatefulWidget { @override State<StatefulWidget> createState() { return new RandomWordsState(); } }
Now, we need to create a class which would manage the state of the stateful widget. I’ll be calling it RandomWordsState.
lass RandomWordsState extends State<RandomWords> { final _suggestions = <WordPair>[]; final _biggerFont = const TextStyle(fontSize: 18.0); @override Widget build(BuildContext context) { return Scaffold ( appBar: AppBar( title: Text('Startup Name Generator'), ), body: _buildSuggestions(), ); } }
The build method will be returning the actual widget which will be rendered on the screen. Instead of adding the scaffold in the main stateless widget, we can add it here as well and just return the entire widget as one.
Note, that we have added two field items, _suggestions, and _biggerFont. Adding an Underscore is just a DART convention to denote private methods and properties. We will be storing our random words to display in _suggestions and _biggerFont will be used to add styling to our text.
Now, we’ll create the _buildSuggestions method and add it to RandomWordsState class:
Widget _buildSuggestions() { return new ListView.builder( padding: const EdgeInsets.all(10.0), itemBuilder: (context, i) { if (i.isOdd) return Divider(); final index = i ~/ 2; // If you've reached at the end of the available word pairs... if (index >= _suggestions.length) { // ...then generate 10 more and add them to the suggestions list. _suggestions.addAll(generateWordPairs().take(10)); } return _buildRow(_suggestions[index]); }, ); }
This method returns the ListView widget which will then be added to the body of the Scaffold we created earlier.
Notice that we return a divider in case “i” is odd, this is because even the dividers are treated as items in ListView, and since dividers start after the first Item (whose index is 0), the index of dividers will be odd always.
Next, we check whether more words need to be added to the list and if so, then add 10 at a time.
Now we have initialized the ListView, but how do we tell flutter the layout of the list Items.
Building ListItem
Now, we will create the _buildRow method which will return a widget, which is essentially a layout describing how the list items must look. You can do all sorts of things with it, but for this example, we will simply be adding a text to the row item:
Widget _buildRow(WordPair pair) { return new ListTile( title: new Text(pair.asPascalCase, style: _biggerFont), ); }
Here’s how your main.dart should look like at the end:
import 'package:flutter/material.dart'; import 'package:english_words/english_words.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "List in Flutter", home: new Scaffold( appBar: new AppBar( title: Text("List"), ), body: RandomWords(), ), ); } } class RandomWords extends StatefulWidget { @override State<StatefulWidget> createState() { return new RandomWordsState(); } } class RandomWordsState extends State<RandomWords> { final _suggestions = <WordPair>[]; final _biggerFont = const TextStyle(fontSize: 18.0); @override Widget build(BuildContext context) { return Scaffold ( appBar: AppBar( title: Text('Startup Name Generator'), ), body: _buildSuggestions(), ); } Widget _buildSuggestions() { return new ListView.builder( padding: const EdgeInsets.all(10.0), itemBuilder: (context, i) { if (i.isOdd) return Divider(); final index = i ~/ 2; // If you've reached the end of the available word pairings... if (index >= _suggestions.length) { // ...then generate 10 more and add them to the suggestions list. _suggestions.addAll(generateWordPairs().take(10)); } return _buildRow(_suggestions[index]); }, ); } Widget _buildRow(WordPair pair) { return new ListTile( title: new Text(pair.asPascalCase, style: _biggerFont), ); } }
Congratulations!! you have created our very first listview in Flutter. In the next tutorial, I will show you how to add actions to listview items such as what happens when you tap on a list item, and also how to build a more complex listview item.
If you want to stay updated with all the latest articles, subscribe to the weekly newsletter by entering your email address in the form on the top right section of this page.
Like what you read ? Don’t forget to share this post on Facebook, Whatsapp and LinkedIn.
You can follow me on LinkedIn, Quora, Twitter and Instagram where I answer questions related to Mobile Development, especially Android and Flutter.