Chema Rubio

@develodroid

Flutter III - Lists and Items — [Flutter 1.0]

The third post about Flutter will focus on explaining how to build a list of items. A scrollable Contacts View containing widgets representing each contact will be implemented along the article.

Updated to Flutter 1.0 — December 2018

Index

TIP: The whole Flutter series code is available in this repository.

Overview

Before reviewing the code, let´s talk about what is going to be done and how. First of all, to get a Contacts View done, the view will contain three different kind of widgets as you can see in the image below.

  • ContactListItem Shows each contact information.
  • ContactList To build a contacts list, this widget will be used containing a list of ContactListItem widgets.
  • ContactsPage This Widget holds the whole page and is made from an AppBar Widget and the ContactListItem list.

Main & MaterialApp

As seen in previous posts, main() calls runApp method containing a MaterialApp Widget.

The home attribute will take a ContactsPage Widget instance as a parameter.

Contact Data

To make the example as simple as possible, ContactsList constructor will take data created directly in the code (hardcoded). How to fetch data using services will be explained in the next article.

First thing to be done is creating a file called contact_data.dart at the same level the main.dart file is, inside lib folder.

Next step is defining a class to specify the contact data, i.e: name, email, phone number, address, etc… inside contact_data.dart file.

It is a simple class where a contact data is defined. Using {} to make the parameters the constructor takes as optional allows to reference them by name. What is more, constructor is defined as a const in order to create instance constants in compilation time.

Next step is creating a sample contacts list, the example below represents a list populated with two contacts.

Take a look to the first sentence, the left side const kContacts, defines a constant which can´t be reassigned. In the right side, const <Contact> [] defines an immutable list. Inside this list a Contact instance must be created for each existing contact. By the time we want a new contact to be created we use const Contact instead of new Contact so it becomes a constant at compilation time. As you can see, marking Contact class attributes as optional allows to assign them by name.

ContactListItem

Let´s talk about the three widgets from in to out. The inner one is ContactListItem.

In previous posts, it was explained that Flutter provides two different type of widgets, StatelessWidget and StatefulWidget. The ContactListItem will be a StatelessWidget and the reason why it´s because this Widget will show information that won´t change at all, a contact will always have the same data. The example below shows how this Widget should look like.

Same way it was done with the contacts data, create a file for the contact widgets, name it contact_view.dart and place it inside lib folder where main.dart and contact_data.dart where stored.

The constructor takes a contact as a parameter and a ListItem Widget instant must be returned by the build method. This is a Widget provided by Flutter and keeps Material Design specifications, it would be possible to return other widgets (Text, Image…) but using ListItem Widget will save much work.

Some ListItem attributes are:

  • leading It is a Widget that is placed before the title, it is usually an image representing the user or a letter inside a circle or CircleAvatar in Flutter.
  • title Widget defining the first text line
  • subtitle Widget defining the second text line, it is placed under the title.

Here an example of a ListItem structure.

In this example, the ListItem built has a Text representing the first letter in the contact name nested to a CircleAvatar as leading. It also has a Text showing contact fullName as title and its email as subtitle.

A shorter way to define the ContactListItem is making it to extend ListItem because is what is already being returned from the build method.

ContactList

Once the items are done, let´s go for the list. A MaterialList Widget will be used. This Widget internally returns a ScrollableList Widget which allows to build a scrollable list.

Both ContactListItem and ContactList widgets are StatelessWidgets, in this case the contacts list is declared as final.

In order to use Contact class, its file (contact_data.dart) must be imported at the top of the file in which is going to be used the following way.

import ‘contact_data.dart’;

In the example above a MaterialList Widget is returned in the build method, some of the specified attributes are type that describes ítems with title and subtitle, vertical padding and children that carries a list of ContactListItem.

The function _buildContacList will be in charge of creating the list, it will iterate the contact data list and map it into a ContactListItem, at last create a list containing all those ContacListItems using toList method.

If you are not familiar with funcional programming, the Next function would be equivalent.

List<_ContactListItem> _buildContactList() {
    var items = new List<_ContactListItem>();
    for (var contact in _contacts){
items.add(new _ContactListItem(contact));
}
    return items;
}

Contacts Page

The last Widget needed must contain an AppBar and a ContactList.

ContactsPage extends StatlessWidget because it won´t change its state. This Widget will be created using an Scaffold instance so it provides a layout in which an AppBar and a List could be located inside.

In this example an AppBar is added to the Scaffold and the attribute body takes a contacts list instance (ContactList Widget). ContactList was created using kContacts which was created inside contact_data.dart.

To finish, just set a new ContactPage inside MaterialApp home attribute.

home: new ContactsPage()

Run the application and see the contacts list.

To sum up

After creating a contacts list using Flutter, let´s think about how this same work could be achieved the native way using Android.

We could use two different .xml files, one of them to define an AppBar and a RecyclerView and another one to define the contact´s layout. An Activity (or both an Activity and a Fragment), and Adapter and a ViewHolder are also needed.

The difference between the amount of code and time are quite big. This post shows how powerful is Flutter in terms of specification.

Next article will focus in how to create a MVP (Model-View-Presenter) architecture using Flutter.

All the code shown in this tutorial is available here if you missed something.

More by Chema Rubio

Topics of interest

More Related Stories