When building mobile applications in Flutter, lists are one of the most common UI patterns. Whether it’s displaying messages in a chat, rendering items in an e-commerce catalog, or showing a list of settings, developers rely heavily on ListView.
Flutter provides several constructors for ListView, such as:
ListView.builderfor efficient list building.ListView.customfor advanced cases.ListView.separatedfor building lists with dividers or separators between items.
This article explores ListView.separated in depth, focusing on:
- Why and when to use
ListView.separated. - Adding dividers and spacing between list items.
- Creating custom separators like icons, gradients, or styled widgets.
- Real-world examples with practical code snippets.
- Best practices for clean and reusable list UIs.
Introduction to ListView.separated
A ListView in Flutter is a scrollable column of widgets. Normally, when you use ListView.builder, you get an efficient list of items but without any built-in separation between them.
For example, consider this code:
ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text("Item $index"),
);
},
);
This creates a simple list of items with no dividers or spacing. To make the UI clearer and more structured, we often want separators between items.
That’s where ListView.separated comes in.
What is ListView.separated?
ListView.separated is a special constructor that allows you to define both:
- Item Builder → how each item looks.
- Separator Builder → what widget appears between items.
The method signature is:
ListView.separated({
required IndexedWidgetBuilder itemBuilder,
required IndexedWidgetBuilder separatorBuilder,
required int itemCount,
});
- itemBuilder: Builds the main list item.
- separatorBuilder: Builds the widget placed between items.
- itemCount: Number of items in the list.
Adding Dividers and Spacing
The most common use case for ListView.separated is adding dividers or spacing between list items.
Example: Adding Simple Dividers
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text("Item $index"),
);
},
separatorBuilder: (context, index) {
return Divider(
color: Colors.grey,
thickness: 1,
);
},
);
- Each list item is built with
itemBuilder. Divideris used in theseparatorBuilderto separate items visually.
This results in a neat list with thin horizontal lines.
Example: Adding Spacing Instead of Dividers
Sometimes you don’t want a line, just empty space. You can use a SizedBox.
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text("Item $index"),
);
},
separatorBuilder: (context, index) {
return SizedBox(height: 16);
},
);
This creates spacing between each list item without drawing a line.
Example: Combining Divider and Spacing
You can even combine both by wrapping a Divider with padding.
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text("Item $index"),
);
},
separatorBuilder: (context, index) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Divider(
color: Colors.blue,
thickness: 2,
),
);
},
);
This creates a bold divider with spacing on either side, giving a clean, material-style design.
Custom Separators
The true power of ListView.separated comes when you build custom separators. Instead of simple dividers, you can insert any widget between items.
Example: Custom Colored Box Separator
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text("Product $index"),
);
},
separatorBuilder: (context, index) {
return Container(
height: 8,
color: Colors.grey[200],
);
},
);
Here, instead of a line, a light grey background separates items.
Example: Separator with Text
You can insert labels or headings between items.
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
title: Text("Message $index"),
);
},
separatorBuilder: (context, index) {
return Center(
child: Text(
"--- Divider $index ---",
style: TextStyle(color: Colors.grey),
),
);
},
);
This places text as a separator, useful for grouping messages or events by time.
Example: Using an Icon Separator
ListView.separated(
itemCount: 6,
itemBuilder: (context, index) {
return ListTile(
title: Text("Step ${index + 1}"),
);
},
separatorBuilder: (context, index) {
return Icon(Icons.arrow_downward, color: Colors.blue);
},
);
This creates a stepper-style list, where an arrow icon separates items.
Example: Gradient Separator
ListView.separated(
itemCount: 5,
itemBuilder: (context, index) {
return ListTile(
title: Text("Task $index"),
);
},
separatorBuilder: (context, index) {
return Container(
height: 4,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.purple, Colors.pink],
),
),
);
},
);
Instead of a plain line, you get a colorful gradient separator, adding a modern touch to the UI.
Real-World Use Cases
1. Chat Application
- Messages need spacing.
- Use
ListView.separatedwithSizedBox(height: 10).
2. Settings Page
- Each setting option separated by a
Divider. - Clean and professional look.
3. E-Commerce Product List
- Use separators with light background colors to distinguish between items.
4. Steps or Onboarding Flow
- Use arrows or numbers as separators to indicate flow.
Performance Considerations
ListView.separatedis more efficient than manually inserting dividers in the item list.- Only items and separators that are visible are built, ensuring good performance on long lists.
- Always use
ListView.separatedinstead of manually adding dividers insideitemBuilderwithColumn.
Best Practices
- Keep separators subtle
- Don’t overpower content; dividers should guide the eye, not dominate.
- Use spacing when dividers feel cluttered
SizedBoxoften provides a cleaner design.
- Use separators for grouping
- Labels or headings as separators improve readability.
- Test in both light and dark modes
- Ensure dividers are visible but not distracting.
- Avoid complex widgets as separators for huge lists
- Keep separators lightweight for performance.
Leave a Reply