Scrolling layouts
ListView, SingleChildScrollView, and Scrollbar
It's time to deal with that RenderFlex overflow warning. This happens anytime your content extends beyond the boundary of a widget and you haven't set up scrolling.
Choosing a scrolling widget#
When you have content that needs to scroll, think about how you want the UX to work.
Do you want to scroll a full page at a time, like an image carousel? Use a PageView widget.
Do you want a grid of widgets that wrap in one direction and scroll in the other? Use a GridView widget.
Do you want a list of equally-sized widgets (like a Row or Column) that scroll smoothly, with (optionally) Flutter disposing any off-screen widgets and re-rendering them when they come into the viewport? Use a ListView widget.
Do you want a list of widgets that scroll smoothly but render all at once, may be of very different sizes, and don't get disposed when they're off-screen? Use a SingleChildScrollView widget.
There are several widgets that offer more granular and customized scrolling behavior. You normally won't need them, but you can find a full list here.
The goal is to scroll the _ProfileContent widget, which has a top-level Column. This means the choice is between ListView and SingleChildScrollView. Both would be acceptable here, but there's a compelling reason to choose one over the other. Let's examine both.
ListView#
tl;dr: You should use ListView when you have a medium or long list that repeats the same inexpensive widget.
To use a ListView, all you have to do is replace the top-level Column
in _ProfileContent with ListView
. That's really it, as long as you're using a vanilla Column with no extra parameters. These widgets have the children
parameter in common. (You'll also want to wrap the CircularProgressIndicator in _ProfileClientList with a Center widget so it doesn't get stretched out to the full width of the screen.)
ListView has a few performance optimizations over SingleChildScrollView. These depend on all of its children being about the same size in the scroll direction (vertical by default). If they're different sizes, it will still work, but you may see some weirdness with the scrollbar—it will change size and jump around as you scroll through the page.
If you're fine-tuning performance or dealing with scrollbar jank that just won't go away, consider using the itemExtent
parameter on any kind of ListView to tell Flutter the exact height (in logical pixels) it should expect each item to be. This is both faster and more predictable than letting it figure that out on its own.
ListView has a couple of named constructors you should be aware of.
ListView.builder#
ListView.builder
lets you generate a list of widgets from an array. You'll use an itemBuilder
instead of a children
list (you've already used the Builder pattern with LayoutBuilder and FutureBuilder, so you should find it familiar) and provide an itemCount
parameter with the number of widgets you want to display. itemBuilder
will be called with the array index of the widget being built. Typical usage looks something like this:
class ListViewBuilderExample extends StatelessWidget {
When you use this ListView variant, Flutter will lazy-load your widgets, only building the ones that are currently visible on the screen. This is great for really long lists where you use the same widget over and over again with different data and want to speed up the app by only rendering what the user is looking at.
ListView.separated#
This lesson preview is part of the Line-of-Business Mobile Apps with Flutter and Dart course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Line-of-Business Mobile Apps with Flutter and Dart, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
