ListView

The ListView widget is an extremely useful widget for displaying a list of items in a linear arrangement (vertical or horizontal). ListView is an advanced version of the Column widget that automatically provides scrolling when the list of items won't fit on the screen.

ListView provides a way to efficiently display a list of data in a manner that is both visually attractive and practical for managing large amounts of data. It can support both static and dynamic data.

Adding ListView widget

Let's see how you can use the ListView widget by building an example that shows a list of users.

Here's how it looks:

To do so:

  1. Add the ListView widget from the Layout Elements. If you are adding it inside the Column widget, ensure to set the ListView widget to Expanded so that it takes up all the available space.

  2. Inside the ListView widget, you can add a widget to display the user name (e.g., Text, ListTile). For this example, let's add a widget from templates named 'List 1 - User'. After adding, you can delete the unnecessary widgets.

  3. Let's fill the list view with some dummy user names. To do so, select the ListView widget, head over to properties panel, and select Generate Dynamic Children.

    1. Enter the Variable Name that will hold the list of names. You'll use this variable in step 4.

    2. Set the Value to Sample Data > List of Random Names. Tip: If you want a specific number of items, you can enter the value in min and max list length.

  4. Now select the widget on which you want to display the name, head over to the properties panel, open 'set from variable menu' and select the [dynamic_children_variable_name] item.

Also, see how to retrieve and display data from Firebase, Supabase, and API calls.

Showing backend data

You probably want to show a list of items from your backend. There are primarily the following sources from where you can get the data.

1. Showing data from Firestore

To show data from Firestore, create a collection, query a collection and then display the data in a widget, such as the Text and Image widget.

2. Showing data from API call

You may be using your own infrastructure to store your app data. The data can be retrieved via API calls.

Let's build a simple page that fetches and display pictures from https://picsum.photos/v2/list.

Prerequisites

If you haven't, be familiar with API calls 101.

2.1 Add API call

The first step is to create an API call in your project. After adding an API call in FlutterFlow, it looks like this:

2.2 Making API call on a ListView

Making an API call allows you to get a response (containing the list of items) and show them in the ListView.

To make an API call on a ListView:

  1. Select the ListView widget.

  2. Head over to the properties panel and click on the Backend Query tab.

  3. Set the Query Type to API Call.

  4. Set the Group or Call Name to the API that you added.

  5. Click Confirm.

2.3 Generate Dynamic Children

Generating dynamic children help you prepare a list of items present in the API response. The returned result is stored in a variable (aka dynamic children variable) that you can use to populate the ListView.

To generate dynamic children:

  1. Select ListView widget.

  2. Head over to the properties panel and click on the Generate Dynamic Children.

  3. Enter the appropriate Variable Name.

  4. Set the Value to the [apicall_name] Response.

  5. Set the Response Options to JSON Body and Available Options to JSON Path.

  6. Set the JSON Path Name to Custom and then set the JSON Path using JSON expression to retrieve the list. See how to get JSON Path here. For this example, enter the $[*] ,which will retrieve all data inside the '[]' i.e., all objects inside the array list.

  7. Click Confirm.

2.4 Showing Data in UI Elements

To show data from JSON response into a widget:

  1. Select the Image widget, move to the properties panel, find the Path property, and click on the Set from Variable text.

  2. Select the [variable_name] item from the list. This should be the variable name you specified while Generating Children from Variable.

  3. Set the Available Options to JSON Path.

  4. Inside the JSON Path, enter the JSON expression to retrieve the image URL. For this example, enter the $.download_url.

  5. Click Confirm.

  6. Similarly, Select the Text Widget. Move to the properties panel and set the data for the Text property.For this example, enter the $.author.

3. Showing data from Supabase

To show data from Supabase, create a table, query a Supabase table and then display the data in the Image and Text widget.

Adding infinite scroll

The infinite scroll automatically loads the new items as you scroll down the list. It works by showing only a limited number of items (e.g., 15, 25) at first and loads subsequent items before the user reaches the end of the list. At the end of the list, a circular progress bar is visible as the new items are loaded.

Adding infinite scroll helps you improve the user experience by reducing the initial waiting time (as without infinite scroll, it would take more time to load the long list) and loading new items only when required.

The infinite scroll can be added to the list of items retrieved from two sources:

Infinite scroll on a list from the Firestore collection

In FlutterFlow, you can directly enable the infinite scroll on a list of items received from the Firestore collection.

To enable the infinite scroll:

  1. Query a collection on a ListView (skip if you have already done so).

  2. Select the ListView, move to the properties panel and, select the Backend Query section.

  3. Scroll down the already added query and turn on the Enable Infinite Scroll.

  4. On enabling the infinite scroll, the Listen For Changes property also gets enabled. That means the list automatically updates if changes are made to the item. This is done to keep all the items up to date on the screen. However, it does not update the list if any new item is added or deleted. In rare cases, you would need to disable this feature. To do so, turn off this property.

  5. In infinite scroll, the items are loaded in chunks called pages. The number of items to load on a single page is determined by the Page Size property. By default, the value is set to 25 (i.e., load 25 items per page). The ListView loads the first page as soon as it is visible on the screen, and the subsequent pages (with the number of items defined in the Page Size property) are loaded as you scroll down the screen. You can adjust this value according to your design and requirement.

  6. Click Save.

Infinite scroll on a list from API call

To add an infinite scroll on the API call, you must have an endpoint that supports pagination with at least one query parameter that accepts a page number like page, offset, etc.

Pagination Variables

When you add the paginated API call in the builder and enable the infinite scroll, we provide you the following pagination variables that you can pass to your API variables. These will be available inside the Set Variable menu.

  1. Next Page Index: You can pass this variable for the query parameter that accepts the page number. The default value is 0 and keeps increasing by one as you scroll down the list until it reaches the end.

  2. #(Number of) Loaded Items: This equals the number of items returned by the paginated API call.

  3. Last Response: This is useful if you want to get anything from the last response that might help you retrieve the next set of data.

Pro tip: When passing the Number of Loaded Items for query parameters like limit, per_page, size, etc., use a Specific Value, such as 15,20.

Adding infinite scroll includes:

1. Add paginated API call

The paginated API is the API that returns the result in chunks. Most of the paginated API requires you to add the query parameters to know how many items to retrieve and from where to start.

For example, this API call https://reqres.in/api/users?per_page=20&page=1 requires per_page parameter that specifies 20 items to load per page, and page parameter tells to start from the first page. This is called page-based pagination.

See how to add the paginated API call by adding query parameters.

2. Passing pagination variable in API call query

This step includes adding the ListView -> ListTile widget and querying the paginated API call.

  1. While querying the API call, pass the query parameter value from the pagination variable.

Scroll to the beginning or end

See how to scroll to the beginning or end with a click of a button.

Customizing

You can customize the appearance and behavior of this widget using the various properties available under the properties panel.

Showing items horizontally

The default axis for laying out children for ListView is Vertical. To change the axis direction, move to the Properties Panel > ListView Properties and set the Axis to Horizontal.

In most cases, switching the axis may require you to redesign the item.

Shrinking the ListView

By default, the ListView widget takes up all the available space in its main axis. That means if the Axis property is set to Vertical, ListView will occupy all vertical space on the screen. Similarly, if the Axis is set to Horizontal, then ListView will reserve all the horizontal space.

To make the ListView only take the size of its children, select the ListView, head over to the Properties Panel > ListView Properties, and enable the Shrink Wrap property.

Reverse list

Most recent items are the most relevant, so reversing a list can help display newer items first. For instance, In a chat application, messages are typically displayed in reverse order, i.e., the newest at the bottom.

To reverse the list, select the ListView, head over to the Properties Panel > ListView Properties, and enable the Reverse property.

Reorder list

You might want to allow users to change the sequence of items in a list within an app through interactive methods like drag-and-drop. For instance, a music app where users can create their playlists. They can drag songs to rearrange the play order based on their current mood or preference.

Reordering a list works only if you have a dynamic list of items.

Let's see how to allow users to reorder the list items stored in app state variable.

  1. First, create an app state variable with a few items of type String and display them on the ListView widget.

  2. Then, select the ListView, head over to the Properties Panel > ListView Properties, and enable the Reorderable property.

  3. Select Actions from the properties panel (the right menu), and Open the Action Flow Editor.

  4. You'll see an On Reorder callback. Actions under this are triggered when a user finishes repositioning an item in the UI. But, we also need to update the item position in the actual list as well. To do so, we can create a custom action that will modify the item index in the list.

    1. Create a custom action with three arguments that accept the actual list, old index, and new index. Tip: You'll get the old and new index from Set Variable menu > Reorderable ListView.

    2. The custom action looks like this:

    3. Here's the code for the custom action with an explanation:

    // Define a function called reorderItems that returns a Future of a list of strings.
    // It takes in a list of strings, an old index, and a new index as parameters.
    Future<List<String>> reorderItems(
      List<String> list,
      int oldIndex,
      int newIndex,
    ) async {
      // If the item is being moved to a position further down the list
      // (i.e., to a higher index), decrement the newIndex by 1.
      // This adjustment is needed because removing an item from its original
      // position will shift the indices of all subsequent items.
      if (oldIndex < newIndex) {
        newIndex -= 1;
      }
    
      // Remove the item from its original position in the list and store
      // it in the 'item' variable.
      final item = list.removeAt(oldIndex);
    
      // Insert the removed item into its new position in the list.
      list.insert(newIndex, item);
    
      // Return the modified list.
      return list;
    }
  5. The custom action returns the modified list, which you can use to update the actual list using the update app state variable action.

If you want to reorder the list items retrieved via Firebase query collection, the steps are almost similar except for the following changes.

Reordering items in a Firebase query is only suited for smaller lists. For larger datasets, this method can be inefficient and might lead to performance issues. Additionally, frequent writes and updates to Firebase can increase costs significantly.

  1. Create 'order' field in the collection.

  2. Query collection order by 'order' field.

  3. Ensure that the Infinite scroll is disabled.

  4. Replace the custom action code with the below one:

Future reorderFirebaseItems(
  List<PlaylistRecord> list,
  int oldIndex,
  int newIndex,
) async {
  // If the item is being moved down the list, we adjust the newIndex.
  if (oldIndex < newIndex) {
    newIndex -= 1;
  }

  // Remove the item from its current position in the list.
  final PlaylistRecord item = list.removeAt(oldIndex);
  
  // Insert the item into its new position.
  list.insert(newIndex, item);

  // Create a batch to combine multiple Firestore operations into one.
  final batch = FirebaseFirestore.instance.batch();

  // Iterate through the list and update the order field for each document in Firestore.
  for (int i = 0; i < list.length; i++) {
    final PlaylistRecord doc = list[i];
    // Update the 'order' field of the document with its new index. 
    // This assumes that you have an 'order' field in Firestore where you store the order of the items.
    batch.update(doc.reference, {
      'order': i
    }); 
  }

  // Commit all the batched operations to Firestore.
  return await batch.commit();
}

Enable pull to refresh

To enable pull to refresh on this widget, follow the instructions here.

Showing empty list widget

See how to display an empty list widget when there is no data.

Add item spacing

See how to add space between items here.

Show or hide widget

See how to show or hide any widget using the Conditional Visibility property.

Responsive visibility

See how to add responsive visibility to any widget.

Add padding & alignment

See how to add padding and alignment to any widget.

Primary property

See how to use the primary property here.


Video guide

If you prefer watching a video tutorial, here's the one for you:


Last Updated Date: September 15, 2023

Last updated