YouTube Description:

The basics of Flutter ListView. Includes an example of using the ListView with simple widgets, as well as connecting a list to the ListView with ListView Builder. With the ListView Builder I show how to display the list, add entries to the list, and remove entries from the list. Also includes examples of ListView Separator, and ListTile's Leading and Trailing.

Start with the typical boilerplate:

import 'package:flutter/material.dart'; void main() => runApp(ListViewApp()); class ListViewApp extends StatelessWidget { const ListViewApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text("ListView Example"), ), ), ); } }
 

Now the Simplest ListView we could add:

home: Scaffold( appBar: AppBar( title: Text("ListView Example"), ), body: ListView( children: [ Text('A'), Text('B'), Text('C'), ], ), //ListView ), //Scaffold
 

we dress it up a little bit

body: ListView( children: [ ListTile( title: Text('A'), ), // ListTile ListTile( title: Text('B'), ), // ListTile ListTile( title: Text('C'), ), // ListTile ], ), // ListView
 

And it doesn't have to just be ListTiles:

children: [ ListTile( title: Text('A'), ), ListTile( title: Text('B'), ), ElevatedButton( child: Text('Press Me'), onPressed: () {}, ), ],
 

So that's the simplest way you can use a ListView, but you can also use it with a List. We'll start by creating a sample List.

class ListViewApp extends StatelessWidget { final List<String> entries = ['A', 'B', 'C']; @override

And then we will convert our ListView into a ListView.builder:

body: ListView.builder( itemCount: entries.length, itemBuilder: (context, index) { return ListTile( title: Text('${entries[index]}'), ); // ListTile }, ), // ListView.builder

Now it still looks the same but it's pulling it from a List.

 

So let's say we were building a grocery list app. The app would allow you to enter in items you need from the store and then delete them if you either don't need them anymore, or have already purchased them. We will start by clearing out the List because we don't want to start with any groceries:

class ListViewApp extends StatelessWidget { final List<String> entries = []; @override

And then we will add a condition around the ListView.builder that if there are no records in the entries list to show a message stating so:

body: entries.length > 0 ? ListView.builder( itemCount: entries.length, itemBuilder: (context, index) { return ListTile( title: Text('${entries[index]}'), ); }, ) : Center( child: Text('No Groceries in your list.'), ),

And now you should see the message in the example to the right.

 

Now we need a way to add our groceries to the list. We can start by going ahead and converting our StatelessWidget to a StatefulWidget:

class ListViewApp extends StatefulWidget { @override _ListViewAppState createState() => _ListViewAppState(); } class _ListViewAppState extends State<ListViewApp> { final List<String> entries = [];

And then we will add a text field into our AppBar:

appBar: AppBar( title: TextField(), ),

And then add a floatingActionButton:

child: Text('No Groceries in your list.'), ), // Center floatingActionButton: FloatingActionButton( child: Icon(Icons.save), onPressed: () {}, ), // FloatingActionButton ), //Scaffold
 

So now we will hook up a controller to the TextField so we can access it through the FloatingActionButton

class _ListViewAppState extends State<ListViewApp> { final List<String> entries = []; final textController = TextEditingController(); @override Widget build(BuildContext context) {

Tie it to the TextField:

appBar: AppBar( title: TextField( controller: textController, ), // TextField ), //AppBar

And then add the setState to the FloatingActionButton that adds the text from the TextField to the entries list:

floatingActionButton: FloatingActionButton( child: Icon(Icons.save), onPressed: () { setState(() { entries.add(textController.text); }); }, ),

Now if you enter, say, Apples into the text box in the AppBar and press the save button, you should see an entry in the ListView!

 

You'll notice though that when you type something into the text box and hit the save button, it doesn't go away. We can fix that easily by adding a clear below the add:

onPressed: () { setState(() { entries.add(textController.text); textController.clear(); }); },

Now if you add a few more grocery items to your list, it will clear out when you press the save button.

 

You may have noticed though that they're not in alphabetical order. That's easy to fix as well, we just need to sort the entries above at the top of the build widget like so:

Widget build(BuildContext context) { entries.sort(); return MaterialApp(

And now they will be in the correct order.

 

So now we need a way to delete the entries from the ListView. we're going to do that by using the onLongPress in the ListTile.

return ListTile( title: Text('${entries[index]}'), onLongPress: () { setState(() { entries.removeAt(index); }); }, ); // ListTile

hold your finger or cursor down on one of the grocery items for a few seconds and it should disappear now.

 

You can also add a divider in between the entries by using ListView.separated:

? ListView.separated( itemCount: entries.length, itemBuilder: (context, index) { return ListTile( title: Text('${entries[index]}'), onLongPress: () { setState(() { entries.removeAt(index); }); }, ); }, separatorBuilder: (BuildContext context, int index) => const Divider(), )

maybe make it a little darker so it's easier to see

const Divider( color: Colors.black, ),
 

And we can add a grocery icon to the beginning of the entries:

return ListTile( leading: Icon(Icons.local_grocery_store), title: Text('${entries[index]}'),

You can also use trailing to put one at the end.

 

So this gives you the basics of a ListView, but it has one major flaw...

If you close the app... it all disappears.

How do we fix that? Well, we will talk about that... in a future video!

 
 

More Videos