Migration to Flutter Guide
Discover our battle-tested 21-step framework for a smooth and successful migration to Flutter!
Home
Glossary

ListView in Flutter

What is ListView in Flutter?

ListView is a scrollable widget that arranges its children linearly in one direction. Unlike Column or Row, ListView handles:

  • Scrolling
  • Viewport constraints
  • Efficient widget creation and recycling

This makes it suitable for feeds, settings screens, long forms, and any UI where content may exceed the available screen space.

Column vs ListView in Flutter

Understanding the difference between Column and ListView is essential. This is one of the most common beginner mistakes in Flutter app development.

Column in Flutter

  • Lays out all children at once.
  • Does not support scrolling.
  • Easily causes overflow errors.
  • Suitable only for small, fixed layouts.

ListView in Flutter

  • Supports scrolling by default.
  • Works with large or dynamic content.
  • Builds widgets lazily when needed.
  • Handles viewport constraints correctly.

If content can grow or should scroll, ListView is almost always the correct choice.

ListView.builder in Flutter

ListView.builder is the most commonly used and recommended constructor.

It creates list items lazily, meaning widgets are built only when they become visible on screen. This is critical for performance when working with data from APIs, databases, or any list larger than a few dozen items.

A simple rule of thumb:

  • small, static lists like settings or menus: regular ListView
  • dynamic data or long lists: always ListView.builder

Using ListView with a children list generated by a for-loop may look convenient, but it scales poorly and should be avoided for real data.

ListView.separated in Flutter

ListView.separated is a variant of ListView.builder that inserts a separator widget between items.

It is commonly used for:

  • dividers between list items
  • spacing between rows
  • visual grouping without modifying item widgets

Both items and separators are built lazily, making it safe for large lists.

Example of ListView in Flutter

ListView.separated(
  itemCount: 20,
  separatorBuilder: (_, _) => const Divider(),
  itemBuilder: (context, index) => ListTile(
    title: Text('Item $index'),
  ),
);

This pattern is ideal for settings screens and simple scrollable lists.

ListView inside Column: the biggest trap

One of the most common Flutter errors appears when placing a ListView inside a Column or Row.

The typical error message is: Vertical viewport was given unbounded height

The reason is simple:

  • Column wants to know how tall its children are.
  • ListView wants infinite height so it can scroll

This creates a layout conflict.

The solution is to wrap ListView with Expanded (or Flexible), which tells Flutter to give the list the remaining available space.

Without Expanded, ListView inside Column or Row will almost always break.

Common mistakes with ListView

Typical issues include:

  • using Column instead of ListView for scrollable content
  • placing ListView inside Column without wrapping it in Expanded
  • using ListView(children: […]) for large or dynamic datasets
  • generating list items eagerly with for-loops
  • nesting multiple scrollable widgets without understanding constraints

Learn more

Flutter open source packages by LeanCode

6 Non-obvious Flutter and Dart Packages

Almost every production-grade app depends on tens of packages. Using them allows for quick implementation of standard functionalities. Take a closer look at 6 useful but not-so-popular Dart and Flutter packages made and tested by LeanCode's devs.

12 Flutter & Dart Code Hacks
by LeanCode

12 Flutter & Dart Code Hacks & Best Practices – How to Write Better Code?

In this article, we’re sharing LeanCode’s 12 practical Flutter and Dart patterns that help you write less boilerplate, make your code cleaner, and catch mistakes earlier. Apply these patterns and you'll find yourself coding faster, communicating more clearly with your teammates, and spending less time debugging issues that the compiler could have caught.