Flutter ListView Tutorial and Examples.
In this tutorial we want to look at one of the most important widgets especially when it comes to rendering lists of data, the ListView.
What is a ListView?
A ListView is a scrollable list of widgets arranged linearly.
As the names suggests it's responsibility is list items. These items can then scrolled. ListView isn't the only scrolling view. There are others like gridview, however ListView is the most commonly used.
ListView will display its children one after another in the scroll direction. In the cross axis, the children are required to fill the ListView.
Here's a simple infinite listview:
new ListView.builder(
padding: new EdgeInsets.all(8.0),
itemExtent: 20.0,
itemBuilder: (BuildContext context, int index) {
return new Text('entry $index');
},
)
More ListView documentation can be found here.
Let's look a flutter ListView example with onClick.
Why ListView?
Well ListViews are probably the most commonly used widgets for displaying lists of data. In most cases we use it together with CardViews. And in fact render images and text. You may have already seen countless apps with lists of images and text.
If it is flutter application, then chances are that either gridview or listview has been used.
ListViews and GridViews are important because given the nature(small screen) of mobile devices, you always need to have the ability to scroll through data. The screen can only display a small of data per viewport. So we need a component that can easily be scrolled.
Also the fact that most of mobile apps by their nature require the ability to show lists of data. Mobile apps are not mostly used for heavy data entry like Microsoft Word, Excel etc in PC. Rather majority of apps require us to fetch data from the server and render to the user. These types of apps need widgets like ListViews.
Flutter Examples
Let us now look at some full examples.
Section 1: Basic ListViews
Let's start by looking at really simple and basic listviews to introduce you to ListView creation. The examples in this section only contain one single file so you can easily copy to your project. They also don't require any special depdency or configuration.
Example 1: Flutter Simple ListView with OnClick Example
This is a simple flutter listview example to display items from a flutter fixed-length list, otherwise known as an array in other languages. Obviously we write our app in Dart programming language.
Here is the demo:
If the user clicks a single cardview, a CupertinoAlertDialog
will be rendered with the clicked item.
The dialog will have some text and icon.
And here's our video tutorial:
Here are the files we explore:
- pubspec.yaml
- lib/main.dart
Step 1: pubspec.yaml
No external dependency is needed:
name: simple_listview
description: A Simple ListView Flutter application.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
Step 2: main.dart
This is where we write our flutter code in dart programming language. In Dart it is very common to write several classes in a single file. So this simple file will have three classes.
Importing Packages in Flutter/Dart
But first we need to import some packages and we do that using the import
keyword in dart.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
Here are the packages we are importing:
- material.dart : will give us material design widgets and theme.
- cupertino.dart : Will give us
CupertinoAlertDialog
as well as cupertino icons.
Creating classes in Flutter/Dart
In Dart like in most C style programming languages you create a class using the class
keyword. Classes are encapsulation mechanism in Object Oriented Programming languages.
In this case we create three classes:
1.class MyApp extends StatelessWidget {..}
class Home extends StatefulWidget {..}
class _HomeState extends State<Home> {..}
Our first class is deriving from StatelessWidget and implementing the build()
method. That method will build a materialapp
widget with title, home and theme set and return it as a widget.
The second class will derive from StatefulWidget and override the createState()
method.
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter ListView',
home: new Home(),
theme: new ThemeData(primaryColor: Colors.orange),
);
}
}
class Home extends StatefulWidget {
@override
_HomeState createState() => new _HomeState();
}
class _HomeState extends State<Home> {
@override
Widget build(BuildContext context) {
var spacecrafts = ["James Web","Enterprise","Hubble","Kepler","Juno","Casini","Columbia","Challenger","Huygens","Galileo","Apollo","Spitzer","WMAP","Swift","Atlantis"];
var listItem = new ListView.builder(
itemCount: spacecrafts.length,
itemBuilder: (BuildContext context, int index) {
return new ListTile(
title: new Card(
elevation: 5.0,
child: new Container(
alignment: Alignment.centerLeft,
margin: new EdgeInsets.only(top: 10.0, bottom: 10.0),
child: new Text(spacecrafts[index]),
),
),
onTap: () {
showDialog(
barrierDismissible: false,
context: context,
child: new CupertinoAlertDialog(
title: new Column(
children: <Widget>[
new Text("ListView"),
new Icon(
Icons.favorite,
color: Colors.red,
),
],
),
content: new Text( spacecrafts[index]),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: new Text("OK"))
],
));
},
);
},
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Flutter ListView")
),
body: listItem,
);
}
}
void main() {
runApp(new MyApp());
}
Flutter ListView with Images and text
Let's look at a simple example to render images/icons and text in a ListView in ListTiles. This is a very basic example.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build (BuildContext context){
final title = 'Basic List';
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: ListView(
children: <Widget>[
ListTile(
title: Text('Map'),
leading: Icon(Icons.map),
),
ListTile(
title: Text('Photo Album'),
leading: Icon(Icons.photo_album),
),
ListTile(
title: Text('Phone'),
leading: Icon(Icons.phone),
),
],)
)
);
}
}
Conclusion
Simply copy the code into your main.dart
file. It is only a single file. We've looked at how to implement a simple listview with cardviews. When the user clicks a cardview we open a curperdino dialog.
Let us now look at other examples in the next sections.
Example 2: ListView TextFields
This is yet another simple Listview example. In this example we will look at how to render TextFields in a Listview.
Here is the demo of what is created:
Step 1: Create Project
Start by creating an empty Flutter project.
Step 2: Dependencies
No special dependency is needed for this project.
Step 3: Write Code
We will be buiding several custom widgets. For example here is how we build a card widget:
Widget card = Center(
child: Card(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding:
const EdgeInsets.fromLTRB(12.0, 24.0, 50.0, 12.0),
child: const ListTile(
leading: Icon(
Icons.account_balance_wallet,
color: Colors.redAccent,
size: 50.0,),
title: Text(
'€ 54.08',
style: TextStyle(
fontSize: 40.0, fontWeight: FontWeight.bold
),
textAlign: TextAlign.center,
),
subtitle: Text(
'EUR · Euro',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold
),
textAlign: TextAlign.center,
),
),
),
],
),
),
);
Here is how we build our button section:
Widget buttonSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildButtonColumn(Icons.call, 'CALL'),
buildButtonColumn(Icons.near_me, 'ROUTE'),
buildButtonColumn(Icons.share, 'SHARE')
],
),
);
Here is the full code:
main.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: new ListDisplay(),
);
}
}
class ListDisplay extends StatefulWidget {
_ListDisplayState createState() => _ListDisplayState();
}
class Tx {
String type;
double amount;
DateTime dateTime;
Tx(this.type, this.amount, this.dateTime);
}
class TxList {
DateTime dateTime;
Tx tx;
TxList(this.dateTime, this.tx);
}
class _ListDisplayState extends State<ListDisplay> {
List<String> listItems = ["first", "second", "the quick brown fox", "jumps over", "the lazy dog!"];
final List<Tx> txns = new List<Tx>();
final List<TxList> txnLists = new List<TxList>();
var dateTimeFormatter = new DateFormat('yyyy-MM-dd H:m:s');
var dateFormatter = new DateFormat('yyyy-MM-dd');
//print(new DateFormat.yMMMMEEEEd().format(new DateTime.now()));
@override
void initState() {
super.initState();
setState(() {
txns.add(new Tx("Transfer to A", 20.0, DateTime.now()));
txns.add(new Tx("Transfer to B", -10.0, DateTime.now()));
txns.add(new Tx("Transfer to C", 200.0, DateTime.now()));
txns.add(new Tx("Transfer to D", -50.0, DateTime.now()));
txns.add(new Tx("Transfer to E", -24.0, DateTime.now()));
txns.add(new Tx("Transfer to F", 190.0, DateTime.now()));
//new list
txnLists.add(new TxList(DateTime.now(), new Tx("Transfer to A", 20.0, DateTime.now())));
txnLists.add(new TxList(DateTime.now(), new Tx("Transfer to B", -10.0, DateTime.now())));
txnLists.add(new TxList(DateTime.now(), new Tx("Transfer to C", 200.0, DateTime.now())));
txnLists.add(new TxList(DateTime.now(), new Tx("Transfer to D", -50.0, DateTime.now())));
txnLists.add(new TxList(DateTime.now(), new Tx("Transfer to E", -24.0, DateTime.now())));
txnLists.add(new TxList(DateTime.now(), new Tx("Transfer to F", 190.0, DateTime.now())));
});
}
final TextEditingController textEditingController = new TextEditingController();
@override
Widget build(BuildContext context) {
Widget buildBody(BuildContext context, int index) {
return Card(
child: Text(listItems[index]),
);
}
Widget titleSection = Container(
padding: const EdgeInsets.all(32.0),
child: Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(bottom: 8.0),
child: Text(
'Oeschinen Lake Campground',
style: TextStyle(
fontWeight: FontWeight.bold,
),
)
),
Text(
'Kandersteg, Switzerland',
style: TextStyle(
color: Colors.grey[500],
),
),
]
)
),
Icon(
Icons.star,
color: Colors.red[500],
),
Text('41'),
],)
);
Column buildButtonColumn(IconData icon, String label) {
Color color = Theme.of(context).primaryColor;
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(icon, color: color),
Container(
margin: EdgeInsets.only(top: 8.0),
child: Text(
label,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
Widget buttonSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildButtonColumn(Icons.call, 'CALL'),
buildButtonColumn(Icons.near_me, 'ROUTE'),
buildButtonColumn(Icons.share, 'SHARE')
],
),
);
Widget textSection = Container(
padding: EdgeInsets.all(32.0),
child: Text(
'''
Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese Alps. Situated 1,578 meters above sea level, it is one of the larger Alpine Lakes. A gondola ride from Kandersteg, followed by a half-hour walk through pastures and pine forest, leads you to the lake, which warms to 20 degrees Celsius in the summer. Activities enjoyed here include rowing, and riding the summer toboggan run.
''',
softWrap: true,
),
);
Widget gridView = new Expanded(
child: GridView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(listItems[position]),
);
},
itemCount: listItems.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
)
);
Widget card = Center(
child: Card(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding:
const EdgeInsets.fromLTRB(12.0, 24.0, 50.0, 12.0),
child: const ListTile(
leading: Icon(
Icons.account_balance_wallet,
color: Colors.redAccent,
size: 50.0,),
title: Text(
'€ 54.08',
style: TextStyle(
fontSize: 40.0, fontWeight: FontWeight.bold
),
textAlign: TextAlign.center,
),
subtitle: Text(
'EUR · Euro',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold
),
textAlign: TextAlign.center,
),
),
),
],
),
),
);
Widget emailView = ListView.builder(
itemCount: listItems.length,
itemBuilder: (context, position) {
Tx txn = txns[position];
TxList txnList = txnLists[position];
return Column(
children: <Widget>[
// ListTile(
// title: Text(
// dateFormatter.format(txnList.dateTime),
// style: Theme.of(context).textTheme.headline,
// ),
// ),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
//mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
// Text(
// "5m",
// style: TextStyle(color: Colors.grey),
// ),
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
Icons.credit_card,
size: 35.0,
color: Colors.grey,
),
),
],
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding:const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 6.0),
child: Text(
txn.type,
style: TextStyle(
fontSize: 22.0, fontWeight: FontWeight.bold),
),
),
Padding(
padding:const EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 12.0),
child: Text(
dateTimeFormatter.format(txn.dateTime),
style: TextStyle(fontSize: 18.0),
),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
//crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(
txn.amount.toString(),
style: TextStyle(fontSize: 18.0),
),
],
),
),
],
),
Divider(
height: 2.0,
color: Colors.grey,
)
],
);
},
);
return Scaffold(
appBar: new AppBar(
title: new Text('ListView with TextBox'),
),
body: new Column(
children: <Widget>[
card,
Padding(
padding:const EdgeInsets.fromLTRB(12.0, 24.0, 12.0, 12.0),
child: Text(
'Recent transactions',
style: TextStyle(
fontSize: 24.0, fontWeight: FontWeight.normal
),
textAlign: TextAlign.center,
),
),
//titleSection,
//buttonSection,
// new TextField(
// controller: textEditingController,
// onSubmitted: (text) {
// listItems.add(text);
// textEditingController.clear();
// setState(() {});
// },
// ),
//textSection,
// new Expanded(
// child: new ListView.builder(
// itemCount: listItems.length,
// itemBuilder: (BuildContext ctxt, int index) {
// return buildBody(context, index);
// }
// )
// ),
new Expanded(
child: emailView,
),
//gridView,
],
),
);
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Section 2: ListView with Letter Icons
In this section you will learn how to create a ListView with letter icons, for example like those you see in Contact apps.
Example 1: Flutter ListView with Icons and Text - Contact App
This example will teach you how to create a listview with letter icons. See the demo screenshot below:
Step 1: Create Project
Start by creating an empty Flutter project.
Step 2: Dependencies
No special dependency is needed for this project. We also do not need to make any special configuration.
Step 3: Create Model class and Dummy Data
The model class that will hold our Contact data. Then the dummy data to represent our contacts:
contact_data.dart
class Contact {
final String fullName;
final String email;
const Contact({this.fullName, this.email});
}
const List<Contact> kContacts = const <Contact>[
const Contact(
fullName: 'Romain Hoogmoed', email: '[email protected]'),
const Contact(fullName: 'Emilie Olsen', email: '[email protected]'),
const Contact(fullName: 'Téo Lefevre', email: 'té[email protected]'),
const Contact(fullName: 'Nicole Cruz', email: '[email protected]'),
const Contact(fullName: 'Ramna Peixoto', email: '[email protected]'),
const Contact(fullName: 'Jose Ortiz', email: '[email protected]'),
const Contact(
fullName: 'Alma Christensen', email: '[email protected]'),
const Contact(fullName: 'Sergio Hill', email: '[email protected]'),
const Contact(fullName: 'Malo Gonzalez', email: '[email protected]'),
const Contact(fullName: 'Miguel Owens', email: '[email protected]'),
const Contact(fullName: 'Lilou Dumont', email: '[email protected]'),
const Contact(
fullName: 'Ashley Stewart', email: '[email protected]'),
const Contact(fullName: 'Roman Zhang', email: '[email protected]'),
const Contact(fullName: 'Ryan Roberts', email: '[email protected]'),
const Contact(fullName: 'Sadie Thomas', email: '[email protected]'),
const Contact(fullName: 'Belen Serrano', email: '[email protected] ')
];
Step 4: Create Contact Details Page
Build a screen to render the details of a single Contact in textfields:
/pages/contact_details.dart
import 'package:flutter/material.dart';
import '../models/contact_data.dart';
class ContactViewPage extends StatelessWidget {
final Contact contact;
ContactViewPage({Key key, this.contact}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(contact.fullName),
),
body: Container(
child: Text(contact.email),
));
}
}
Step 5: Create Contacts List Page
This is the screen that will list all the contacts in a listview:
/pages/contact_view.dart
import 'package:flutter/material.dart';
import '../models/contact_data.dart';
import 'contact_details.dart';
class ContactsPage extends StatelessWidget {
Drawer buildDrawer(BuildContext context) {
var header = DrawerHeader(
child: Container(
child: Text("Contact App Header"),
));
var about = AboutListTile(
child: Text("About Contact"),
applicationName: "Contact App Example",
applicationVersion: "V0.0.1",
applicationIcon: Icon(Icons.hourglass_empty),
icon: Icon(Icons.info),
);
ListTile buildNavItem(var icon, String label, String route) {
return ListTile(
leading: Icon(icon),
title: Text(label),
onTap: () {
// FIXME: Need Stateful Widget
// setState(() {
// Navigator.of(context).pop();
// Navigator.of(context).pushNamed(route);
// });
},
);
}
var navList = [
header,
buildNavItem(Icons.home, "Home", "/"),
buildNavItem(Icons.settings, "Settings", "/contact_details"),
buildNavItem(Icons.account_balance_wallet, "Account", "/account"),
about
];
ListView listView = ListView(children: navList);
return Drawer(child: listView);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Contacts"),
),
drawer: buildDrawer(context),
body: Container(
child: ContactList(kContacts),
));
}
}
class ContactList extends StatelessWidget {
final List<Contact> _contacts;
ContactList(this._contacts);
@override
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.symmetric(vertical: 8.0),
itemCount: _contacts.length,
itemBuilder: _buildContacts,
);
}
Widget _buildContacts(context, index) {
return ContactItem(_contacts[index]);
}
}
class ContactItem extends StatelessWidget {
const ContactItem(this.contact);
final Contact contact;
Widget _buildTiles(BuildContext context, Contact contact) {
return ListTile(
title: Text(contact.fullName),
subtitle: Text(contact.email),
leading: CircleAvatar(
child: Text(contact.fullName[0]),
),
trailing: Icon(Icons.card_travel),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
// TODO: 어떻게 page간 데이터를 넘기는지?
return ContactViewPage(contact: contact);
// return Scaffold(
// appBar: AppBar(
// title: Text(contact.fullName)
// ),
// body: Text('Hello'),
// );
},
),
);
},
);
}
@override
Widget build(BuildContext context) {
return _buildTiles(context, contact);
}
}
Step 6: Create Main class
The main class of this app:
main.dart
import 'package:flutter/material.dart';
import './pages/contact_view.dart';
void main() {
runApp(new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(primarySwatch: Colors.blue),
home: new ContactsPage(),
));
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Section 3: ListView with Images and Text
In this section we will look at the following:
- Create a ListView with CardViews with Images and text
Example 1: Creating a Simple ListView using Columns
This next example is an alternative way to create a ListView. It teaches you how to implement a listview with cardviews that contain images and text. However this time round we create a simple listview using Columns
as opposed to the ListItemBuilder
.
Check the screenshot below to see how it looks:
Step 1: Create Project
Start by creating an empty Flutter project in your IDE or editor.
Step 2: Dependencies
No special dependencies are needed for this project. However we will register our assets folder inside the pubspec.yaml
pubspec.yaml
# To add assets to your application, add an assets section, like this:
assets:
- img/
Step 3: Create a Person Object
We now need to create our model class. In this case the Person
class is that model class, alongside it's properties like name and profile image:
Person.dart
class Person {
String name;
String profileImg;
String bio;
Person({this.name,this.profileImg,this.bio});
}
Step 4: Create Main class
Here is how you design a single person's detail card:
Widget personDetailCard(Person) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Card(
color: Colors.grey[800],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 50.0,
height: 50.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(Person.profileImg)
)
)),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(Person.name,
style: TextStyle (
color: Colors.white,
fontSize: 18
),
),
Text(Person.bio,
style: TextStyle (
color: Colors.white,
fontSize: 12
),
)
],
)
],
),
),
),
);
}
Here is the full code:
main.dart
import 'package:flutter/material.dart';
import 'package:custom_list_flutter_app/Person.dart';
void main() => runApp(MaterialApp(
home: MyHome(),
));
class MyHome extends StatefulWidget {
@override
_MyHomeState createState() => _MyHomeState();
}
class _MyHomeState extends State<MyHome> {
List<Person> persons = [
Person(name: 'Bill Will', profileImg: 'img/pic-1.png', bio: "Software Developer"),
Person(name: 'Andy Smith', profileImg: 'img/pic-2.png', bio: "UI Designer"),
Person(name: 'Creepy Story', profileImg: 'img/pic-3.png', bio: "Software Tester")
];
Widget personDetailCard(Person) {
return Padding(
padding: const EdgeInsets.all(10.0),
child: Card(
color: Colors.grey[800],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 50.0,
height: 50.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
image: AssetImage(Person.profileImg)
)
)),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(Person.name,
style: TextStyle (
color: Colors.white,
fontSize: 18
),
),
Text(Person.bio,
style: TextStyle (
color: Colors.white,
fontSize: 12
),
)
],
)
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[900],
body: Padding(
padding: const EdgeInsets.fromLTRB(10, 50, 10, 10),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(Icons.menu, size: 35, color: Colors.white),
Text('Notifications',
style: TextStyle (
color: Colors.white,
fontSize: 25
),
),
Icon(Icons.notifications_none, size: 35, color: Colors.white)
],
),
Column(
children: persons.map((p) {
return personDetailCard(p);
}).toList()
)
],
),
),
);
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Example 2: Swipe-Dismiss ListView with CardView, Images and Multiple Text
This example will contain cardview with images and multiple text for each row on our Card. We use ListView.Builder
. The rows or rather the cards can be swiped and dismissed subsequently.
Here is the demo of the project:
Here are what you will learn:
- How to implement listview with images and multiple text.
- How to implement swipe to dismiss in a listview.
- How to load ListView images from the network using
NetworkImage
.
Step 1: Create Project
Start by creating an empty Android Studio
project.
Step 2: Dependencies
No special dependency or configuration is needed for this project.
Step 3: Create Swipeable ListView
Replace your main.dart
with the following code:
main.dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("List view"),
),
body: Center(child: SwipeList()));
}
}
class SwipeList extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return ListItemWidget();
}
}
class ListItemWidget extends State<SwipeList> {
List items = getDummyList();
@override
Widget build(BuildContext context) {
return Container(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Dismissible(
key: Key(items[index]),
background: Container(
alignment: AlignmentDirectional.centerEnd,
color: Colors.red,
child: Icon(
Icons.delete,
color: Colors.white,
),
),
onDismissed: (direction) {
setState(() {
items.removeAt(index);
});
},
direction: DismissDirection.endToStart,
child: Card(
elevation: 5,
child: Container(
height: 100.0,
child: Row(
children: <Widget>[
Container(
height: 100.0,
width: 70.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5),
topLeft: Radius.circular(5)
),
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage("https://is2-ssl.mzstatic.com/image/thumb/Video2/v4/e1/69/8b/e1698bc0-c23d-2424-40b7-527864c94a8e/pr_source.lsr/268x0w.png")
)
),
),
Container(
height: 100,
child: Padding(
padding: EdgeInsets.fromLTRB(10, 2, 0, 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
items[index],
),
Padding(
padding: EdgeInsets.fromLTRB(0, 3, 0, 3),
child: Container(
width: 30,
decoration: BoxDecoration(
border: Border.all(color: Colors.teal),
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: Text("3D",textAlign: TextAlign.center,),
),
),
Padding(
padding: EdgeInsets.fromLTRB(0, 5, 0, 2),
child: Container(
width: 260,
child: Text("His genius finally recognized by his idol Chester",style: TextStyle(
fontSize: 15,
color: Color.fromARGB(255, 48, 48, 54)
),),
),
)
],
),
),
)
],
),
),
),
);
},
));
}
static List getDummyList() {
List list = List.generate(10, (i) {
return "Item ${i + 1}";
});
return list;
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Example 3: ListView with Images and Chips - onTap with GestureDetector
This example teaches you how to create a simple listview containing cardview with images and Chips. We handle click events using GestureDetector.
Check the demo screenshot below:
Here are what you will learn:
- Create a listview with images and text.
- Use GestureDetector - When the user taps an item in our list, we will capture the event using GestureDetector and thus show a dialog
- Create a Listview with Chips - Our text will be rendered on a chip.
Step 1: Create Project
Start by creating an empty flutter project.
Step 2: Dependencies
In you pubspec.yaml
add photo_view
as a dependency:
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.2
photo_view: ^0.5.0
Also register the images folder as a asset:
# To add assets to your application, add an assets section, like this:
assets:
- images/hacker.jpeg
Step 3: Create ListView
We create our ListView using the ListView.Builder
:
main.dart
import 'package:flutter/material.dart';
import 'package:photo_view/photo_view.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
appBarTheme: AppBarTheme(color: Colors.green),
primarySwatch: Colors.purple,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text('Simple Card view'),
),
body: new ListView.builder(
padding: const EdgeInsets.all(16),
itemBuilder: (context, i) {
return Container(
height: 130,
child: Card(
// color: Colors.blue,
elevation: 10,
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: GestureDetector(
onTap: () {
},
child: Container(
width: 100.0,
height: 100.0,
decoration: BoxDecoration(
color: Colors.red,
image: DecorationImage(
image: AssetImage('images/hacker.jpeg'),
fit: BoxFit.cover),
borderRadius:
BorderRadius.all(Radius.circular(75.0)),
boxShadow: [
BoxShadow(blurRadius: 7.0, color: Colors.black)
]),
),
),
),
GestureDetector(
onTap: () {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext conext) {
return AlertDialog(
title: Text('Not in stock'),
content:
const Text('This item is no longer available'),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
},
child: Container(
padding: EdgeInsets.all(30.0),
child: Chip(
label: Text('@anonymous'),
shadowColor: Colors.blue,
backgroundColor: Colors.green,
elevation: 10,
autofocus: true,
)),
),
],
),
),
);
},
),
);
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Section 4: ListView Scroll Examples
In this section we will look at examples regarding scrolling of a listview, be it vertical or horizontal.
Example 1: ListView Scroll Horizontally or Vertically
This example explores how to create a ListView that can scroll in both directions: horizontally or vertically, sideways or up and down.
Here is the demo:
Step 1: Create Project
Start by creating an empty Flutter project.
Step 2: Dependencies
No special or third party dependency is needed. We also do not need any special configuration.
Step 3: Create Horizontal and Vertical ListView
The screen will contain a BottomNavigationBar with three BottomNavigationBarItems. Each item represents a different Listview. Tehre are three listview types in this case: the Normal ListView, the Vertical ListView and the Horizontal ListView.
Here is how you build a widget or screen with a bottom navigation bar:
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: buildListViews(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: index,
items: [
BottomNavigationBarItem(
icon: Text('ListView'),
title: Text('Basic'),
),
BottomNavigationBarItem(
icon: Text('ListView'),
title: Text('Vertical'),
),
BottomNavigationBarItem(
icon: Text('ListView'),
title: Text('Horizontal'),
),
],
onTap: (int index) => setState(() => this.index = index),
),
);
Here is how you build a verical List:`
Widget buildVerticalListView() => ListView.separated(
separatorBuilder: (context, index) => Divider(color: Colors.black),
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
title: Text(item),
);
},
);
And here is how you build a horizontal listview:
Widget buildHorizontalListView() => Container(
height: 100,
child: ListView.separated(
padding: EdgeInsets.all(16),
scrollDirection: Axis.horizontal,
separatorBuilder: (context, index) => Divider(),
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return Container(
alignment: Alignment.center,
margin: EdgeInsets.only(right: 16),
child: Text(item, style: TextStyle(fontSize: 24)),
);
},
),
);
Here is the full code:
main.dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static final String title = 'ListView Example';
@override
Widget build(BuildContext context) => MaterialApp(
debugShowCheckedModeBanner: false,
title: title,
theme: ThemeData(primarySwatch: Colors.deepOrange),
home: MainPage(title: title),
);
}
class MainPage extends StatefulWidget {
final String title;
const MainPage({
@required this.title,
});
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int index = 0;
final items = List.generate(2000, (counter) => 'Item: $counter');
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: buildListViews(),
bottomNavigationBar: BottomNavigationBar(
currentIndex: index,
items: [
BottomNavigationBarItem(
icon: Text('ListView'),
title: Text('Basic'),
),
BottomNavigationBarItem(
icon: Text('ListView'),
title: Text('Vertical'),
),
BottomNavigationBarItem(
icon: Text('ListView'),
title: Text('Horizontal'),
),
],
onTap: (int index) => setState(() => this.index = index),
),
);
Widget buildListViews() {
if (index == 0) {
return buildBasicListView();
} else if (index == 1) {
return buildVerticalListView();
} else if (index == 2) {
return buildHorizontalListView();
} else {
return Container();
}
}
Widget buildBasicListView() => ListView(
children: [
ListTile(
leading: Icon(Icons.arrow_forward_ios),
title: Text('Favourites'),
subtitle: Text('All your favourite widgets'),
trailing: Icon(Icons.star, color: Colors.orange),
),
ListTile(
leading: Icon(Icons.arrow_forward_ios),
title: Text('High Ranked'),
subtitle: Text('All widgets liked by the community'),
trailing: Icon(Icons.mood, color: Colors.blue),
),
ListTile(
leading: Icon(Icons.arrow_forward_ios),
title: Text('Important'),
subtitle: Text('All widgets that are important to know'),
trailing: Icon(Icons.assistant_photo, color: Colors.black),
),
ListTile(
leading: Icon(Icons.delete_forever, color: Colors.red),
title: Text('Deleted'),
onTap: () {
print('Deleted pressed');
},
),
],
);
Widget buildVerticalListView() => ListView.separated(
separatorBuilder: (context, index) => Divider(color: Colors.black),
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
title: Text(item),
);
},
);
Widget buildHorizontalListView() => Container(
height: 100,
child: ListView.separated(
padding: EdgeInsets.all(16),
scrollDirection: Axis.horizontal,
separatorBuilder: (context, index) => Divider(),
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return Container(
alignment: Alignment.center,
margin: EdgeInsets.only(right: 16),
child: Text(item, style: TextStyle(fontSize: 24)),
);
},
),
);
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
Section 5: How to Sort Data in ListViews
In this section we will look at flutter examples for sorting ListViews, or how to create sortable Lists easily.
Example 1: How to Create a Sortable ListView
This example teaches you how to create a sortable listview in flutter.
Step 1: Create Project
Start by creating an empty flutter project.
Step 2: Dependencies
We do not need any special dependency to create our sortable listview.
Step 3: Create Sortable Listview
The items and the ListView builder are passed via the constructor.
We will create our Listview as a StatefulWidget:
class SortableListView extends StatefulWidget {
final List items;
final IndexedWidgetBuilder itemBuilder;
SortableListView({this.items, this.itemBuilder})
: assert(items != null),
assert(itemBuilder != null);
@override
State createState() => new SortableListViewState();
}
Here is the full code:
main.dart
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
@override
MyAppState createState() => new MyAppState();
}
class MyAppState extends State<MyApp> {
List<String> rows = new List<String>()
..add('Row 1')
..add('Row 2')
..add('Row 3')
..add('Row 4');
@override
Widget build(BuildContext context) {
final title = 'Sortable ListView';
return new MaterialApp(
title: title,
home: new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new SortableListView(
items: rows,
itemBuilder: (_, int index) => new Card(
child: new ListTile(
leading: new Icon(Icons.photo),
title: new Text(rows[index])),
),
),
),
);
}
}
class SortableListView extends StatefulWidget {
final List items;
final IndexedWidgetBuilder itemBuilder;
SortableListView({this.items, this.itemBuilder})
: assert(items != null),
assert(itemBuilder != null);
@override
State createState() => new SortableListViewState();
}
class SortableListViewState extends State<SortableListView> {
@override
Widget build(BuildContext context) {
return new LayoutBuilder(
builder: (context, constraint) {
return new ListView.builder(
itemCount: widget.items.length + 1,
addRepaintBoundaries: true,
itemBuilder: (context, index) {
return new LongPressDraggable<int>(
data: index,
child: new DragTarget<int>(
onAccept: (int data) {
_handleAccept(data, index);
},
builder: (BuildContext context, List<int> data,
List<dynamic> rejects) {
List<Widget> children = [];
// If the dragged item is on top of this item, the we draw
// a half-visible item to indicate that dropping the dragged
// item will add it in this position.
if (data.isNotEmpty) {
children.add(
new Container(
decoration: new BoxDecoration(
border: new Border.all(
color: Colors.grey[600], width: 2.0),
),
child: new Opacity(
opacity: 0.5,
child: _getListItem(context, data[0]),
),
),
);
}
children.add(_getListItem(context, index));
return new Column(
children: children,
);
},
),
onDragStarted: () {
Scaffold.of(context).showSnackBar(
new SnackBar(
content: new Text("Drag the row to change places")),
);
},
feedback: new Opacity(
opacity: 0.75,
child: new SizedBox(
width: constraint.maxWidth,
child: _getListItem(context, index, true),
),
),
childWhenDragging: new Container(),
);
},
);
},
);
}
void _handleAccept(int data, int index) {
setState(() {
// Decrement index so that after removing we'll still insert the item
// in the correct position.
if (index > data) {
index--;
}
dynamic imageToMove = widget.items[data];
widget.items.removeAt(data);
widget.items.insert(index, imageToMove);
});
}
Widget _getListItem(BuildContext context, int index, [bool dragged = false]) {
// A little hack: our ListView has an extra invisible trailing item to
// allow moving the dragged item to the last position.
if (index == widget.items.length) {
// This invisible item uses the previous item to determine its size. If
// the list is empty, though, there's no dragging really.
if (widget.items.isEmpty) {
return new Container();
}
return new Opacity(
opacity: 0.0,
child: _getListItem(context, index - 1),
);
}
return new Material(
elevation: dragged ? 20.0 : 0.0,
child: widget.itemBuilder(context, index),
);
}
}
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |