How to Create Separators for Rows and Columns
We've likely come across the ListView.separated(), which lets us add a separator to each item in List. But what if we want to have this similar behaviour in a row or column?
If you've been developing a Flutter app for some time, you've likely come across the
ListView widget. The
ListView API provides a useful feature called ListView.separated(), which lets you add a separator to each item, similar to the ItemDecoration in RecyclerView in Android.
But what if we want to have this similar behaviour in a row or column? How do we add a separator to it?
Note: From this point forward, a Column will be used as an example. However, the concept applies to Row as well.
Let's say we have a design like this.
There are several ways to achieve it.
This approach is easy to read, but it requires a lot of duplication of
SizedBox(height: 8.0) after each widget. Additionally, when we want to add a new
Text() widget, we need to remember to add
SizedBox() as well.
We use this approach when we have a list of text. Although it removes duplication, it can suffer from readability issues. For example, it is not always clear why
SizedBox(height: 8.0) was added.
This solution fixes the problems from both approaches 1 and 2. However, in my opinion, it seems hacky and misleading because it uses
Padding to fix the separator issue. Therefore, I would recommend using it as a last resort.
Remember, all of the above approaches work; however, each has its own issues with readability, reusability, and maintainability.
A Better Way 🛣️
To address all of these issues, we can create a wrapper called
separator as an extension method on
Iterable<Widget>, like this:
In this extension, we are using generators to easily yield our separator
element after each item.
Yay!! We finally have a use case for generators.
(I have a few more use cases for generators. If you would like me to cover them in the next post, please let me know in the comments.)
We will now use this extension method with the above approaches 1 and 2, as shown below:
separators method removes duplication and improves readability by indicating that this widget will be used as a separator, similar to what we have in
The other reason why I like this extension approach is that you can put things in between the widgets as well.
You can use this extension on any widget that has children of
List<Widget>. For example, you can use it on
Stack, or any other multi-child layout widgets.
What about performance? 🧪
Isn't it unnecessary to create this many lists just to avoid duplication and improve readability?
My argument is that if the list has only 10-20 items, then it won't have any issues. We can safely use the separator approach.
However, if the list contains more than 20-30 items, it is better to use a
ListView. This is because a
ListView is scrollable and performs better. From a practical point of view, if there are more than 20-30 items, the Column/Row will overflow anyway.
Caution ⚠️: Be careful when using the
MainAxisAlignmentproperty in a
Column. You might spend hours debugging to figure out why the widgets are not aligned properly, only to realize in the end that it's because of the separators.
That’s it for now.
You can check the example on DartPad.
Hey there, If you enjoyed this post then would you be able to do me a quick favour and share my latest blog post with your friends and colleagues? I'd really appreciate it and I think it could be valuable to them.
Thank you so much!
Widget Tricks is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.