Flutter ListView.Builder inside SingleChildScrollView not scrollable

4,274

Solution 1

You probably want to have a fixed header and a scrollable list of posts beneath it. To achieve this, you want to structure the build method of your page like this:

Widget build(BuildContext context){
  return Column(children: <Widget>[
      HeaderComponent(title:"Home", hasBackButton:false),
      ListView.builder(
        ...
      ),
    ],
  )
}

Stacking 2 widgets, that are scrollable on the same axis, into each other, often results in bugs ("unlimited dimension", "overflow", etc.), because there is no clear scroll behaviour for where these 2 components overlap.

To implement a Sliver behaviour, use, well, Slivers, like SliverList.

Solution 2

May I ask why you have created a custom header and are not using an AppBar? You can create a custom PreferredSizedWidget that you could pass to your scaffold if you need an excessively customized design (but you can do all elements of your design in the prebuilt AppBar).

It is recommended in the Flutter documentations for SingleChildScrollView to only use it if necessary, and instead use a ListView instead.

When you have a list of children and do not require cross-axis shrink-wrapping behavior, for example a scrolling list that is always the width of the screen, consider ListView, which is vastly more efficient that a SingleChildScrollView containing a ListBody or Column with many children.

If you made your header an AppBar, you could then use ListView.builder(...) as the body of the scaffold.

But if you are insistent on using SingleChildScrollView for this use case, use a ListBody with your externally built widgets passed in as children. If you want to do in-line generation of the list elements, you can use List.generate to generate the list in-line within ListBody.

Keep the Column on the outside, with the first child element of the Column your header, then the SingleChildScrollView with ListBody as its child with your list elements as the children.

Widget build(BuildContext context) => Column(
 children: <Widget>[
   Header(),
   SingleChildScrollView(
     child: ListBody(
       children: List.generate(...),
     ),
   )
 ],
);

EDIT: Or as the other user recommended, you could nest a ListView within the Column and eliminate the SingleChildScrollView entirely, which is more ideal and much more performant.

Share:
4,274
Kamil
Author by

Kamil

Updated on December 22, 2022

Comments

  • Kamil
    Kamil over 1 year

    I've just began Flutter. I made a HeaderComponent which shows the title "Home" at the top and I used the BubbleBottomNavbar plugin which is displayed at the bottom. For the moment, I'm using a list of strings as a mock but will later get a lists of news from an API an loop to display as cards.

    I tried to create as many components as I can and wrap them to reuse the same "MainContainer" everywhere. This one will show the HeaderComponent and a list of widgets it will receive in parameters as content.

    I want to it to be a scrollable view by default. All its widgets in content are well displayed but I keep seeing the "bottom overflowed ..." warning. I tried many components and different way to fix this using Flex component, Expandable, ... but I still can't scroll and keep this warning

    This is my App Render :

    iPhone App Preview

    Here are my build methods :

    MainComponent.dart : MainComponent

    PostsComponent.dart : PostsComponent

    Thank you for the help you'll provide me 🙂