I'm attempting to place a ListView.builder inside a Column that is a peer to a SliverAppBar. Because of this I need to leverage a CustomScrollview and a SliverToBoxAdapter so that the Column can reside inside the CustomScrollView.
This all works fine as long as I set shrinkwrap to true.
But, for performance reasons I do not want to use shrinkwrap (per the official documentation, this is very expensive and negates the performance benefit of having the ListView.Builder lazy load the list items).
The Error is: "RenderFlex children have non-zero flex but incoming height constraints are unbounded". This is because the Column has infinite height.
I would like to not have to hard code the size of the Columns as this will be a responsive/adaptive scaffold.
My code is below - my question is, has anyone been able to use a Column with a ListView.Builder as a child without using shrinkwrap set to true and without hard coding the height?
import 'package:flutter/material.dart';
class TestScaffold extends StatelessWidget {
const TestScaffold({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey[100],
body: CustomScrollView(
slivers: [
SliverToBoxAdapter(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Title 1'),
Expanded(
child: ListView.builder(
//shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 100,
color: Colors.red,
),
);
},
),
),
],
),
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Title 2'),
Expanded(
child: ListView.builder(
//shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 100,
color: Colors.green,
),
);
},
),
),
],
),
),
],
),
)
],
),
);
}
}
You can use SliverFillRemaining
over Row
while inner widget are using Expanded
.
class TestScaffold extends StatelessWidget {
const TestScaffold({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey[100],
body: CustomScrollView(
slivers: [
SliverFillRemaining( //this
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Title 1'),
Expanded(
child: ListView.builder(
//shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 100,
color: Colors.red,
),
);
},
),
),
],
),
),
const SizedBox(
width: 10,
),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('Title 2'),
Expanded(
child: ListView.builder(
//shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 100,
color: Colors.green,
),
);
},
),
),
],
),
),
],
),
)
],
),
);
}
}
I think you will Also like to use SliverPersistentHeader
for your case.