<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/flutter-listview-fully-explained-4-constructors-and-the-patterns-that-matter-u0jofxkbc" -->

---
title: Flutter ListView, Fully Explained: 4 Constructors and...
description: A detailed guide to Flutter's four ListView constructors—default, builder, separated, and custom—explaining when to use each based on list size and behavior...
canonical: https://daily.dev/posts/flutter-listview-fully-explained-4-constructors-and-the-patterns-that-matter-u0jofxkbc
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Flutter ListView, Fully Explained: 4 Constructors and the Patterns That Matter | daily.dev
og:description: A detailed guide to Flutter's four ListView constructors—default, builder, separated, and custom—explaining when to use each based on list size and behavior...
og:url: https://daily.dev/posts/flutter-listview-fully-explained-4-constructors-and-the-patterns-that-matter-u0jofxkbc
og:image: https://api.daily.dev/og/posts/u0JOFxkBC.png
og:image:alt: Flutter ListView, Fully Explained: 4 Constructors and the Patterns That Matter
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Flutter ListView, Fully Explained: 4 Constructors and the Patterns That Matter

**[Kidpech Pianpithak](https://daily.dev/sources/8zbnrh39r9oomsddnxj0u)** · [@kidpechpianpithak](https://daily.dev/kidpechpianpithak) · 5 min read · 3 upvotes · 0 comments

## Summary

A detailed guide to Flutter's four ListView constructors—default, builder, separated, and custom—explaining when to use each based on list size and behavior needs. Covers horizontal scrolling, reverse scrolling, empty states, extent strategies (itemExtent, prototypeItem, itemExtentBuilder), shrinkWrap costs, and state preservation with keys. Updated against Flutter 3.47 stable documentation with a demo tested against Flutter 3.44.2.

## Content

A `ListView` is a scrollable, linear collection of widgets. The confusing part is rarely scrolling itself. It is choosing *how children are created* and giving the list the right space to scroll in.

Think of a restaurant menu: a tiny menu can be printed in full; a feed of thousands of orders should be prepared only as you reach them. Flutter gives us four constructors for exactly this choice.

*Updated against the Flutter 3.47 stable documentation. An equivalent runnable demo was also analyzed and widget-tested with Flutter 3.44.2; it uses APIs shared by those versions.*

![Four ListView constructors and when to use each](https://media.daily.dev/image/upload/s--jA23UyAD--/f_auto/v1790755581/ugc/content_befab4c1-05b9-418f-941d-6be7b8f73676?_a=BAMAMicg0)

## 1. `ListView(...)`: a small, known list

Use the default constructor when you already have a short set of widgets, such as a settings menu. Every child widget in `children` is constructed when this list is built.

```dart
ListView(
  padding: const EdgeInsets.all(16),
  children: const [
    ListTile(title: Text('Profile')),
    ListTile(title: Text('Notifications')),
    ListTile(title: Text('Privacy')),
  ],
)
```

For hundreds of rows, avoid generating a huge `children` list. Use a builder so Flutter creates row widgets on demand.

## 2. `ListView.builder`: a long or growing list

The builder receives an index for each row it needs. Give it `itemCount` whenever the length is known. This helps Flutter estimate scroll extent, and the callback stays within valid indices.

```dart
ListView.builder(
  itemCount: 1000,
  itemExtent: 64, // All rows are 64 logical pixels tall.
  itemBuilder: (context, index) => ListTile(
    title: Text('Message ${index + 1}'),
  ),
)
```

The **row widgets** are lazy; your data source can still be an ordinary in-memory list. Do not return `null` as an informal “end of list” signal when you know the count: it can make the scrollbar and maximum scroll extent inaccurate. If an API has more pages, update your data and `itemCount` as pages arrive.

## 3. `ListView.separated`: rows with gaps or dividers

This is a lazy builder with a second builder for the space **between** items. With three items, you get two separators—none after the last row.

```dart
ListView.separated(
  itemCount: 30,
  itemBuilder: (context, index) => ListTile(
    title: Text('Contact ${index + 1}'),
  ),
  separatorBuilder: (context, index) =>
      const Divider(height: 1),
)
```

Replace the `Divider` with `SizedBox(height: 12)` for card spacing. Notice that `ListView.separated` does **not** accept `itemExtent`, `prototypeItem`, or `itemExtentBuilder`; separators have their own sizes.

## 4. `ListView.custom`: control the child delegate

Reach for this only when the three simpler constructors do not provide the delegate behavior you need. Here the delegate inserts gaps and excludes those gaps from accessibility item indices. The `childCount` is `2 * tasks.length - 1`, so no trailing gap is built.

```dart
const tasks = ['Design', 'Build', 'Review'];

ListView.custom(
  itemExtentBuilder: (index, dimensions) =>
      index.isEven ? 64 : 12,
  childrenDelegate: SliverChildBuilderDelegate(
    (context, index) {
      if (index.isEven) {
        return ListTile(
          title: Text(tasks[index ~/ 2]),
        );
      }
      return const SizedBox(height: 12);
    },
    childCount: tasks.isEmpty ? 0 : tasks.length * 2 - 1,
    semanticIndexCallback: (child, index) =>
        index.isEven ? index ~/ 2 : null,
  ),
)
```

For ordinary gaps, `ListView.separated` is shorter. `custom` earns its place when you need to configure the `SliverChildDelegate` itself, as in this accessibility example.

## Same constructors, different scrolling patterns

**Horizontal carousel:** change the axis and give the list a bounded height. In a horizontal list, children must have a usable width.

```dart
SizedBox(
  height: 76,
  child: ListView.builder(
    scrollDirection: Axis.horizontal,
    itemCount: 12,
    itemBuilder: (context, index) => Padding(
      padding: const EdgeInsets.all(8),
      child: Chip(label: Text('Topic ${index + 1}')),
    ),
  ),
)
```

**Reverse scrolling:** `reverse: true` reverses the scroll direction and layout. It does not sort your source data. Decide your data order separately, especially in chat UIs.

**Padding and physics:** use `padding` for insets, and choose `physics` only when the default interaction is not what your design needs. For a list that must not scroll independently, `physics: const NeverScrollableScrollPhysics()` disables its own scrolling—but first consider whether one parent scrollable would be simpler.

**Empty state:** build a separate widget when the collection is empty:

```dart
items.isEmpty
    ? const Center(child: Text('No items yet'))
    : ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) =>
            ListTile(title: Text(items[index])),
      )
```

## Three layout and performance rules worth remembering

1. **Give a vertical list a bounded height.** Inside a `Column`, `Expanded(child: ListView.builder(...))` usually expresses the intended layout. A horizontal list inside a column needs a height, as shown above.
2. **Use `shrinkWrap: true` only when the list really must size itself to its contents.** Flutter documents that shrink wrapping costs more because its extent may need recalculation during scrolling. Do not use it as a reflex to silence an unbounded-height error.
3. **Use one extent strategy if row size is predictable.** `itemExtent: 64` is for one fixed size; `prototypeItem` measures one representative widget; `itemExtentBuilder` supplies a size per index. These three options are mutually exclusive. For genuinely variable content, let rows measure naturally instead of forcing text into a height that may clip.

A lazy list can destroy a row's element and local state after it leaves the viewport. Keep important business state in your model. Give changing rows stable keys; if builder item order changes, the API's `findChildIndexCallback` (or `findItemIndexCallback` for `separated`) can help Flutter remap existing children. A `PageStorageKey` on each scroll view helps disambiguate saved scroll positions, such as lists in tabs.

When a page needs a `SliverAppBar`, list, and grid in one scrollable, move to `CustomScrollView` with slivers instead of nesting multiple large scroll views.

## The quick decision

- **Small and explicit:** `ListView(children: ...)`
- **Many rows or paged data:** `ListView.builder`
- **Lazy rows with separators:** `ListView.separated`
- **Delegate-level control:** `ListView.custom`

The examples above use no third-party packages. I also checked an equivalent demo with all four constructors and a horizontal list using `flutter analyze` and a widget test.

**Official references:** [ListView API](https://api.flutter.dev/flutter/widgets/ListView-class.html) · [builder](https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html) · [separated](https://api.flutter.dev/flutter/widgets/ListView/ListView.separated.html) · [custom](https://api.flutter.dev/flutter/widgets/ListView/ListView.custom.html) · [shrinkWrap](https://api.flutter.dev/flutter/widgets/ScrollView/shrinkWrap.html) · [horizontal list cookbook](https://docs.flutter.dev/cookbook/lists/horizontal-list) · [Flutter 3.47 release](https://docs.flutter.dev/release/whats-new)

#flutter #dart #mobile

## Similar posts on daily.dev

- [How to Build Scalable and Performant Flutter Applications: A Handbook for Devs](https://daily.dev/posts/how-to-build-scalable-and-performant-flutter-applications-a-handbook-for-devs-0kfs42gni) · freeCodeCamp · 7 upvotes · 0 comments
- [Async widgets Future Builder \(Part -1\)](https://daily.dev/posts/async-widgets-future-builder-part--1--qdwufihmx) · Medium · 0 upvotes · 0 comments
- [How to Build Responsive UIs in Flutter](https://daily.dev/posts/how-to-build-responsive-uis-in-flutter-2hdygyypa) · freeCodeCamp · 5 upvotes · 0 comments
- [Three flutter widgets you may have never used before](https://daily.dev/posts/three-flutter-widgets-you-may-have-never-used-before-unn1w2tbo) · Flutter Community · 3 upvotes · 0 comments

---

Tags: [#mobile](https://daily.dev/tags/mobile), [#flutter](https://daily.dev/tags/flutter), [#dart](https://daily.dev/tags/dart)

[View this post on daily.dev](https://daily.dev/posts/flutter-listview-fully-explained-4-constructors-and-the-patterns-that-matter-u0jofxkbc)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"DiscussionForumPosting","mainEntityOfPage":"https://daily.dev/posts/flutter-listview-fully-explained-4-constructors-and-the-patterns-that-matter-u0jofxkbc","headline":"Flutter ListView, Fully Explained: 4 Constructors and the Patterns That Matter","text":"A detailed guide to Flutter's four ListView constructors—default, builder, separated, and custom—explaining when to use each based on list size and behavior needs. Covers horizontal scrolling, reverse scrolling, empty states, extent strategies (itemExtent, prototypeItem, itemExtentBuilder), shrinkWrap costs, and state preservation with keys. Updated against Flutter 3.47 stable documentation with a demo tested against Flutter 3.44.2.","url":"https://daily.dev/posts/flutter-listview-fully-explained-4-constructors-and-the-patterns-that-matter-u0jofxkbc","datePublished":"2026-09-30T08:11:17.449Z","dateModified":"2026-09-30T08:11:39.615Z","author":{"@type":"Person","name":"Kidpech Pianpithak","url":"https://daily.dev/kidpechpianpithak","image":"https://avatars.githubusercontent.com/u/85755801?v=4","description":"Senior Application Developer | Flutter & Go | Open Source Creator","interactionStatistic":{"@type":"InteractionCounter","interactionType":{"@type":"EndorseAction"},"userInteractionCount":210}},"image":"https://media.daily.dev/image/upload/s--sxbD6z4d--/f_auto/v1790755878/posts/u0JOFxkBC?_a=BAMAMicg0","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":3},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"isPartOf":{"@type":"WebPage","url":"https://daily.dev/sources/8zbnrh39r9oomsddnxj0u","name":"Kidpech Pianpithak"}}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Kidpech Pianpithak","item":"https://daily.dev/sources/8zbnrh39r9oomsddnxj0u"},{"@type":"ListItem","position":3,"name":"Flutter ListView, Fully Explained: 4 Constructors and the Patterns That Matter"}]}
```

