Home > Software design >  ListView.builder with Widget at the bottom of a SingleChildScrollView
ListView.builder with Widget at the bottom of a SingleChildScrollView

Time:08-19

I need a SingleChildScrollView with messages at the bottom.

enter image description here

I found a solution for bottom alignment in SingleChildScrollView here:

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('AppBar'),
        ),
        body: LayoutBuilder(builder: (context, constraints) {
          return SingleChildScrollView(
              child: ConstrainedBox(
                  constraints: BoxConstraints(minWidth: constraints.maxWidth, minHeight: constraints.maxHeight),
                  child: IntrinsicHeight(
                    child: Column(
                        mainAxisSize: MainAxisSize.max,
                        children: [
                          Text('header'),
                          Expanded(
                            child: Container(
                              color: Colors.green,
                              child: Text('body'),
                            ),
                          ),
                          Text('footer'),
                           // MY CODE STARTS
                           ListView.builder(
                             itemCount: 2,
                             itemBuilder: (context, index) {
                               return Text("a "   index.toString());
                             }
                           )
                           // MY CODE ENDS
                        ]
                    ),
                  )
              )
          );
        })
    );
  }
}

However, when I try to add ListView.builder to this solution I get:

The following assertion was thrown during performLayout():
RenderViewport does not support returning intrinsic dimensions.

Calculating the intrinsic dimensions would require instantiating every child of the viewport, which defeats the point of viewports being lazy.

If you are merely trying to shrink-wrap the viewport in the main axis direction, consider a RenderShrinkWrappingViewport render object (ShrinkWrappingViewport widget), which achieves that effect without implementing the intrinsic dimension API.

Could anyone say how to fix it?

CodePudding user response:

Using Expanded inside SingleChildScrollView will get infinite height, It would be better using top Level LayoutBuilder constrains on inner widget. Also the LisView desire infinite height.

As for the UI you are trying to get, It can be done by this, You might not need two scrollable widget.

body: LayoutBuilder(
  builder: (context, constraints) {
    return Column(
      children: [
        Text('header'),
        Expanded(
          child: ListView.builder(
              itemBuilder: (context, index) =>
                  Text("a "   index.toString())

              // MY CODE ENDS

              ),
        ),
        Text('footer'),
      ],
    );
  },
),

Also Using customScrollView provide more flexibility,

return Scaffold(
  bottomNavigationBar: TextFormField(),
  body: LayoutBuilder(
    builder: (context, constraints) {
      return CustomScrollView(
        slivers: [
          SliverAppBar(
            pinned: true,
            title: Text("title"),
          ),
          SliverToBoxAdapter(
            child: Text('top item'),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return Text("a "   index.toString());
              },
            ),
          ),
          SliverToBoxAdapter(
            child: Text('End item'),
          )
        ],
      );
    },
  ),
);

Actually, it can be done many ways.

Not recommended way,

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('AppBar'),
    ),
    body: LayoutBuilder(
      builder: (context, constraints) {
        return SingleChildScrollView(
          child: ConstrainedBox(
            constraints: BoxConstraints(
                minWidth: constraints.maxWidth,
                minHeight: constraints.maxHeight),
            child: Column(
              mainAxisSize: MainAxisSize.max,
              children: [
                Text('header'),
                Container(
                  color: Colors.green,
                  child: Text('body'),
                ),

                Text('footer'),
                // MY CODE STARTS
                ListView.builder(
                    shrinkWrap: true, //not recommended

                    itemCount: 211,
                    itemBuilder: (context, index) {
                      return Text("a "   index.toString());
                    })
                // MY CODE ENDS
              ],
            ),
          ),
        );
      },
    ),
  );
}

CodePudding user response:

It here:

class Home extends StatelessWidget {
  List<String> listData = [
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item",
    "Item"
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('AppBar'),
        ),
        body: ListView.builder(
          itemCount: listData.length   2,
          itemExtent: 100,
          itemBuilder: (context, index) {
            if (index == 0) {
              return Container(
                child: Text('Header'),
              );
            }
            if (index == listData.length   1) {
              return Container(
                child: Text('Footer'),
              );
            }
            return Container(
              child: Text('Item at $index'),
            );
          },
        ));
  }
}
  • Related