简体   繁体   中英

Flutter ListView.Builder inside SingleChildScrollView not scrollable

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 应用预览

Here are my build methods:

MainComponent.dart: 主要组件

PostsComponent.dart: 帖子组件

Thank you for the help you'll provide me

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 .

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.

Hye, As I have struggled with finding the answer. But finally I solved it.

  1. For those who wants their DataTable to scroll vertical as well as horizontal.
Expanded(
    child: ListView(children: [
      Column(
        children: [
           SingleChildScrollView(
                 scrollDirection: Axis.horizontal,
                 child: DataTable(
                          columns: [
                              DataColumn(label: Text('Storage Location')),
                              DataColumn(label: Text('Piece No ')),
                            ],
                          rows:
                              DataRow(
                                 cells: <DataCell>[
                                            DataCell(Text(element["LGORT"])),
                                            DataCell(Text(element["PCNO"])),
                                                  ],
                                     ),
                               ),
                            ),
                     ],
            ),
       ]),
    )
);

You should make the ListView.builder inside a container, so the builder know where to take its Size(Height,Width from).

Widget build(BuildContext context){
  return Container(
     // You can add its height height here or you can leave it empty
     height : YourHeightValue,
     child: ListView.builder(
       ...
     ),
  )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM