Flutter ListView and ScrollPhysics: A Detailed Look

A closer look at the ListView widget and its features.

Some time ago I wrote an article about the basics of using ListView and GridView in Flutter… This article is intended to take a closer look at the ListView class, ScrollPhysics, and the configuration and optimization parameters for the overall widget.

ListView in Flutter is a linear list of scrollable items. We can use it to create a scrollable list or a list of repeating items.

Exploring ListView Types

We’ll start by looking at the ListViews types, and later we’ll look at other features and enhancements to it.

Consider the ListViews types:

  1. ListView

  2. ListView.builder

  3. ListView.separated

  4. ListView.custom

Let’s explore these types one by one:

ListView

This is the default constructor for the ListView class. The ListView simply takes a list of children and makes a scrollable list out of it.

List built using default constructor
List built using default constructor

General code format:

ListView(
  children: <Widget>[
    ItemOne(),
    ItemTwo(),
    ItemThree(),
  ],
),

ListView.builder ()

Constructor builder() builds a repeating list of items. The constructor takes two main parameters: itemCount to count the number of items in the list, and itemBuilder a constructor for each constructed list item.

List built with builder () constructor
List built with builder () constructor

General code format:

ListView.builder(
  itemCount: itemCount,
  itemBuilder: (context, position) {
    return listItem();
  },
),

Tricky trick: since they are not loaded immediately and only the required amount, we don’t really need item Count as a required parameter, so the list can be infinite.

ListView.builder(
  itemBuilder: (context, position) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Text(position.toString(), style: TextStyle(fontSize: 22.0),),
      ),
    );
  },
),
ListView without ItemCount parameter
ListView without ItemCount parameter

ListView.separated ()

In the constructor separated() we generate a list and can specify a separator between each element.

separated ()
separated ()

Basically, we are building two intertwined lists: one as the main one, the other as a dividing one.

Note that the infinite counter discussed in the previous constructor cannot be used here. This constructor enforces the item count itemCount

The code for this type goes like:

ListView.separated(
      itemBuilder: (context, position) {
        return ListItem();
      },
      separatorBuilder: (context, position) {
        return SeparatorItem();
      },
      itemCount: itemCount,
),

This type of list allows you to dynamically define separators, have different types of separators for different types of items, add or remove separators as needed, etc.

This implementation can also be used to insert other types of items (eg advertisements) easily and without making any changes to the main list in the middle of the list items.

The example shows ads when Position is divisible by 4
The example shows ads when Position is divisible by 4

Note: The length of the list of separators is 1 unit less than the list of items, since there is no separator after the last item

ListView.custom ()

Constructor custom(), as its name suggests, allows you to create ListViews with customized functionality for building child list items. The main parameter required for this is SliverChildDelegatethat forms the components. There are the following types SliverChildDelegates :

  1. SliverChildListDelegate

  2. SliverChildBuilderDelegate.

SliverChildListDelegate accepts a direct child list, while SliverChildBuiderDelegate takes IndexedWidgetBuilder (The collector function we are using).

You can use or subclass them to create your own list members.

ListView.builder is essentially a ListView.custom with a function SliverChildBuilderDelegate

ListView’s default constructor behaves like ListView.custom with SliverChildListDelegate

Now that we’re done with the ListViews types, let’s take a look at ScrollPhysics.

Exploring ScrollPhysics

To control scrolling, we set a physical parameter in the ListView constructor. The different types of this parameter are:

NeverScrollableScrollPhysics

NeverScrollScrollPhysics disables scrolling of the list. Use this to disable scrolling of the ListView completely.

BouncingScrollPhysics

BouncingScrollPhysics returns the list back when the list ends. A similar effect is used on iOS.

ClamppingScrollPhysics

This is the default scrolling feature on Android. The list stops at the end and shows an indication of this action.

FixedExtentScrollPhysics

This is slightly different from other lists in the sense that it only works with FixedExtendScrollControllers and the lists that use them. For example, take ListWheelScrollViewthat makes a list that resembles a wheel.

FixedExtentScrollPhysics only scrolls through the items instead of any offset between them.

The code for this example is incredibly simple:

FixedExtentScrollController fixedExtentScrollController =
    new FixedExtentScrollController();
ListWheelScrollView(
  controller: fixedExtentScrollController,
  physics: FixedExtentScrollPhysics(),
  children: monthsOfTheYear.map((month) {
    return Card(
        child: Row(
      children: <Widget>[
        Expanded(
            child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Text(
            month,
            style: TextStyle(fontSize: 18.0),
          ),
        )),
      ],
    ));
  }).toList(),
  itemExtent: 60.0,
),

A few more things to know.

How can I keep items that are removed when working with a list?

Flutter allows you to use a KeepAlive () widget that keeps an item that would otherwise be removed. In the list, items are by default embedded in the widget AutomaticKeepAlive

AutomaticKeepAlives can be disabled by setting in the field addAutomaticKeepAlives value false… This is useful in cases where items do not need to be saved or in a custom version KeepAlive

Why is my ListView indented between the list and the outer widget?

By default the ListView is indented between the list and the outer widget, to remove it set EdgeInsets.all (0.0)

That’s it for this article!

Hope you enjoyed it.

Keep following me to learn more about Flutter, leave your opinions and comments.


Translation of the article was prepared on the eve of the start of the course Flutter Mobile Developer


On the eve of the start of the course, we invite everyone to sign up for a free demo lesson on the topic:
“Graphics in Flutter”

In the lesson, the participants, together with an expert presenter, will analyze how rendering in Flutter works and study the main components of the library dart:ui

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *