Home > Blockchain >  How to gridview item height make dynamic in flutter
How to gridview item height make dynamic in flutter

Time:06-15

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.

Without bottom overflow error

  • 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.

enter image description here

  • 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"
        }
    ]
}

CodePudding user response:

use custom SliverGridDelegate for get what you want

import 'package:flutter/rendering.dart';

class SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight
extends SliverGridDelegate {

 const SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight({
required this.crossAxisCount,
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.height = 56.0,
 })  : assert(crossAxisCount != null && crossAxisCount > 0),
    assert(mainAxisSpacing != null && mainAxisSpacing >= 0),
    assert(crossAxisSpacing != null && crossAxisSpacing >= 0),
    assert(height != null && height > 0);

final int crossAxisCount;
final double mainAxisSpacing;
final double crossAxisSpacing;
final double height;

  bool _debugAssertIsValid() {
  assert(crossAxisCount > 0);
  assert(mainAxisSpacing >= 0.0);
  assert(crossAxisSpacing >= 0.0);
  assert(height > 0.0);
  return true;
}

@override
SliverGridLayout getLayout(SliverConstraints constraints) {
assert(_debugAssertIsValid());
final double usableCrossAxisExtent =
    constraints.crossAxisExtent - crossAxisSpacing * (crossAxisCount - 1);
final double childCrossAxisExtent = usableCrossAxisExtent / crossAxisCount;
final double childMainAxisExtent = height;
return SliverGridRegularTileLayout(
  crossAxisCount: crossAxisCount,
  mainAxisStride: childMainAxisExtent   mainAxisSpacing,
  crossAxisStride: childCrossAxisExtent   crossAxisSpacing,
  childMainAxisExtent: childMainAxisExtent,
  childCrossAxisExtent: childCrossAxisExtent,
  reverseCrossAxis: axisDirectionIsReversed(constraints.crossAxisDirection),
);
 }

 @override
 bool shouldRelayout(
  SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight oldDelegate) {
  return oldDelegate.crossAxisCount != crossAxisCount ||
    oldDelegate.mainAxisSpacing != mainAxisSpacing ||
    oldDelegate.crossAxisSpacing != crossAxisSpacing ||
    oldDelegate.height != height;
 }
 }

in this delegrate you can pass gridview item height

CodePudding user response:

TL, I write it here. Hot reload is working by injecting new, changed source code to the Dart VM which only works when debugging. So after you killed the app or closed the debug session, the VM is down. The only thing you left is the version you first installed when you start debug session. That's why when you reopen it after debug closed, the app is still showing the old error version.

If you want to test it without debug session, you may either

(1) build a release version

(2) just close the debug session and start the debug session again, then the app installed should be the latest version

Ref about hot reload in flutter

  • Related