I'm starting to learn the flutter language and I want to display the product list in GridView. But there is one problem that arises. When I run the app GridView items are displayed perfectly like the below image.
- But when I close the app and open it again (note without the run) then I got a bottom overflow error. The image is below.
- My Code is this
class HomePage extends StatefulWidget {
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
void initState() {
// TODO: implement initState
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(
"Catalog App",
),
),
body: (CatalogModel.products != null && CatalogModel.products!.isNotEmpty)
? Padding(
padding: const EdgeInsets.all(1.0),
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.06),
),
shrinkWrap: true,
itemBuilder: (context, index) {
CatalogItem item = CatalogModel.products![index];
return Expanded(
child: InkWell(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProductDetails(item: item))),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
),
child: Column(
children: [
SizedBox(
width: double.infinity,
height: 220,
child: Image.network(item.image,
fit: BoxFit.cover),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Column(children: [
SizedBox(
width: double.infinity,
child: Text(item.name,
textAlign: TextAlign.start,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.cabin(
fontSize: 16.0,
textStyle: const TextStyle(
fontWeight: FontWeight.bold,
))),
),
Padding(
padding: const EdgeInsets.only(top: 5.0),
child: SizedBox(
width: double.infinity,
child: Text(item.category,
textAlign: TextAlign.start,
style: GoogleFonts.cabin(
textStyle: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 11.0,
color: Color(0xFF808080)))),
),
),
PriceDetailsWidget(
discount: item.discount,
actual_price: item.actual_price,
price: item.price),
const AddToCartWidget(),
])),
],
),
),
),
),
);
},
itemCount: CatalogModel.products?.length,
),
)
: const Center(
child: CircularProgressIndicator(),
),
drawer: MyDrawer(),
);
}
void loadData() async {
await Future.delayed(Duration(seconds: 5));
final catalogJson =
await rootBundle.loadString("assets/files/products.json");
final decodedData = jsonDecode(catalogJson);
final productData = decodedData["products"];
CatalogModel.products = List.from(productData)
.map<CatalogItem>((item) => CatalogItem.fromMap(item))
.toList();
setState(() {});
}
}
PriceDetailsWidget.dart
class PriceDetailsWidget extends StatelessWidget {
final String discount;
final num price, actual_price;
const PriceDetailsWidget({
Key? key,
required this.discount,
required this.actual_price,
required this.price,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SizedBox(
width: double.infinity,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("\$${price}",
textAlign: TextAlign.start,
style: GoogleFonts.cabin(
textStyle: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 14.0,
decoration: TextDecoration.lineThrough,
decorationColor: Color(0xFF808080),
decorationThickness: 3.0,
color: Color(0xFF808080)))),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text(
"\$${actual_price}",
style: const TextStyle(
color: Color(MyTheme.primaryColor),
fontWeight: FontWeight.bold,
fontSize: 14.0,
),
),
),
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Text(
discount,
style: const TextStyle(
color: Colors.red,
fontWeight: FontWeight.normal,
fontSize: 14.0,
),
),
)
],
),
),
);
}
}
AddToCartWidget.dart
class AddToCartWidget extends StatelessWidget {
const AddToCartWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(elevation: 0.0, padding: EdgeInsets.zero),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Icon(
// <-- Icon
CupertinoIcons.cart_fill,
size: 24.0,
),
SizedBox(
width: 5,
),
Text('Add to cart'), // <-- Text
],
),
);
}
}
CatalogModel & CatalogItem
class CatalogModel {
static List<CatalogItem>? products;
}
class CatalogItem {
final String id;
final String name;
final String desc;
final num price;
final num actual_price;
final String discount;
final String color;
final String image;
final String category;
CatalogItem(
{required this.id,
required this.name,
required this.desc,
required this.price,
required this.actual_price,
required this.discount,
required this.color,
required this.image,
required this.category});
factory CatalogItem.fromMap(Map<String, dynamic> map) => CatalogItem(
id: map["id"],
name: map["name"],
desc: map["desc"],
price: map["price"],
actual_price: map["actual_price"],
discount: map["discount"],
color: map["color"],
image: map["image"],
category: map["category"]);
toMap() => {
"id": id,
"name": name,
"desc": desc,
"price": price,
"color": color,
"image": image,
};
}
products.json this file I'm storing in the assets folder
{
"products": [
{
"id": "prod001",
"name": "iPhone 13 Pro",
"desc": "Your iPhone will arrive.",
"price": 1299,
"actual_price": 999,
"discount": "20% off",
"color": "#536858",
"image": "https://d2xamzlzrdbdbn.cloudfront.net/products/66d6056e-e588-4b03-a44b-74685197003622111313.jpg",
"category": "Mobile"
},
{
"id": "prod002",
"name": "iPhone SE (PRODUCT) RED",
"desc": "iPhone SE (PRODUCT) RED",
"price": 429,
"actual_price": 399,
"discount": "15% off",
"color": "#A7090A",
"image": "https://www.neolight.in/wp-content/uploads/2022/01/iPhone_XR_red.jpg",
"category": "Mobile"
}
]
}