This happens because you have to specify the height to GridView
.
I've answered one similar questions here:
https://stackoverflow.com/a/76192690/11976596
You can find the same below-
I had a similar issue, where I had a GridView.builder
inside a SingleChildScrollView
. Now the problem is you can't create a GridView
inside SingleChildScrollView
because both will try to take as much space available which here makes height unbounded/infinte.
So the solution is to wrap the GridView
with a SizedBox
and I always prefer to use GridView.Builder
.
Now the actual question, "How do I know the size of SizedBox
when the list is dynamic ?"
So I wrote this code with a logic to calculate the height of SizedBox
dynamically based on the childAspectRatio
attribute of GridView
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return const MaterialApp(title: 'Dynamic GridView', home: Home());
}
}
class Home extends StatelessWidget {
const Home({super.key});
@override
Widget build(BuildContext context) {
final double width = MediaQuery.of(context).size.width;
final double height = MediaQuery.of(context).size.height;
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
itemGrid(width),
],
),
),
);
}
Widget itemGrid(double width) {
const int count = 16;
const int itemsPerRow = 2;
const double ratio = 1 / 1;
const double horizontalPadding = 0;
final double calcHeight = ((width / itemsPerRow) - (horizontalPadding)) *
(count / itemsPerRow).ceil() *
(1 / ratio);
return SizedBox(
width: width,
height: calcHeight,
child: GridView.builder(
padding: const EdgeInsets.symmetric(horizontal: horizontalPadding),
itemCount: count,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
mainAxisSpacing: 0,
crossAxisSpacing: 0,
crossAxisCount: itemsPerRow,
childAspectRatio: ratio),
itemBuilder: (context, index) {
return SizedBox(
child: Card(
clipBehavior: Clip.hardEdge,
child: Column(
children: [
Expanded(
child: Image.network(
"https://picsum.photos/200?${DateTime.now().millisecondsSinceEpoch.toString()}")),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 4.0),
child: Text(
"Lorem Ipsum is a dummy text, lorem ipsum",
maxLines: 3,
overflow: TextOverflow.ellipsis,
style:
TextStyle(fontSize: 10, fontWeight: FontWeight.bold),
textAlign: TextAlign.start,
),
),
],
),
),
);
},
),
);
}
}
Link to working Dart gist - https://dartpad.dev/?id=05ba8804b19a2978a087c68622000a01
Explanation
count
is the total number of items or itemCount
.
itemsPerRow
is the number of items in a row or crossAxisCount
.
ratio
is the childAspectRatio
attribute of GridView
that usually is used to set size of an item inside grid. ratio
is calculated as width/height.
horizontalPadding
is the horizontal padding given to GridView
(in case of vertical list)
calcHeight
is the calculated height of the SizedBox
just so you don't need to give a fixed height in case of dynamic lists.