In my project i need to display a grid of products,2 in each row. For that I am using GridView.builder() as follows :
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text('New Arrivals'),
const SizedBox(height: 10),
Expanded(
child: Consumer<HomeViewModel>(
builder: (context, model, child) {
if (model.state == ViewState.idle) {
if (model.products.isEmpty) {
return const Center(
child: CircularProgressIndicator(color: Colors.black),
);
}
return GridView.builder(
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context, index) =>
ProductItem(product: model.products[index]),
itemCount: model.products.length,
);
}
return const Center(
child: CircularProgressIndicator(color: Colors.black),
);
},
),
),
],
);
}
However, this is giving an A RenderFlex overflowed by 49 pixels on the bottom.
error on each item. The no. of pixels overflowed is different for different item.I have attached the screenshot for reference. What am I doing wrong and how do I fix it?
product_item.dart
:
class ProductItem extends StatelessWidget {
const ProductItem({Key? key, required this.product}) : super(key: key);
final Product product;
@override
Widget build(BuildContext context) {
return Container(
width: 200,
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 200,
height: 150,
child: Image.network(product.imageUrl!),
),
const SizedBox(height: 13),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
product.category!,
softWrap: true,
style: const TextStyle(
fontSize: 10,
color: Colors.deepPurple,
height: 1.5,
fontWeight: FontWeight.w500,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
product.title!,
softWrap: true,
style: const TextStyle(
color: Colors.black54,
fontSize: 12,
height: 1.8,
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'\$ ${product.price!}',
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w600,
height: 2.4,
),
),
Image.asset('assets/icons/cart_icon.png',
width: 40, height: 40),
],
),
)
],
),
);
}
}
CodePudding user response:
the problem "should" lie within:
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
product.title!,
softWrap: true,
style: const TextStyle(
color: Colors.black54,
fontSize: 12,
height: 1.8,
fontWeight: FontWeight.w500,
),
),
),
try using: AutoSizeText instead of Text
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: AutoSizeText(
product.title!,
softWrap: true,
maxLines: 1,
style: const TextStyle(
color: Colors.black54,
fontSize: 12,
height: 1.8,
fontWeight: FontWeight.w500,
),
),
),
CodePudding user response:
Default childAspectRatio
is 1 on GridView
. The issue arise because it is not fitting inside the square. Item's size is depending on screen width. And width is controlling the height,=> aspect ratio.
You can play with size of grid item using childAspectRatio:width/height
. Alternative, you can follow @Maurizio Mancini's answer.
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 3 / 4,//this
),
CodePudding user response:
I have used your code to reproduce the issue. If I understood your needs right, here is the fix:
The main problem is related to childAspectRatio.
return GridView.builder( shrinkWrap: true, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, mainAxisSpacing: 10, crossAxisSpacing: 10, childAspectRatio: 0.75, ), itemBuilder: (context, index) => ProductItem(product: model.products[index]), itemCount: model.products.length, );
So you need to set the aspect ratio similar to this to fix the problem.
You can access the working source code through GitHub.