How to tell a GridView builder to take only necessary height?

1.9k views Asked by At

Is it possible to make a GridView.builder that takes the height of its children, instead of specifying a certain height on its parent?

I have a GridView.builder that is supposed to put the content of a list. I get an error because I didn't specify height on the parent container, but I would like the GridView to take only the minimal necessary height so the children fit.

This is my GridView:

return SizedBox(
      // height: 400,
      child: GridView.builder(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          childAspectRatio: MediaQuery.of(ctx).size.width /
              (MediaQuery.of(ctx).size.height / 4),
          crossAxisCount: MediaQuery
              .of(ctx)
              .size
              .width > 600 ? 3 : 1,
        ),
        itemCount: content.length,
        itemBuilder: (BuildContext ctx, index) {
          return SizedBox(
            height: 100,
            width: 300,
            child: ListTile(
              leading: content[index]["icon"],
              title: content[index]["title"],
              subtitle: Expanded(
                child: Text(
                  content[index]["text"],
                  style: const TextStyle(fontSize: 18),
                ),
              ),
            ),
          );
        },
      ),
    );

The list is something like this:

List content = [
      {"icon": ...,
        "title": ...,
        "text": ...},
      {"icon": ...,
        "title": ...,
        "text": ...},
      {"icon": ...,
        "title": ...,
        "text": ...},
      {"icon": ...,
        "title": ...,
        "text": ...},
    ];

And these are some of the errors that appear on my console: enter image description here

enter image description here

enter image description here

This is what I get if I remove the SizeBox wrapping the GridView:

enter image description here

Note how index 0 has size but on index 1 it is missing. I don't know what that means.

Could somebody help me? My doubt is pretty basic but I attached my code in case I am the one doing something wrong which is very specific.

Thank you in advance.

2

There are 2 answers

0
harizh On

Yes it is possible with minHeight & maxHeight property inside BoxConstraints... The errors you facing because of not mentioned width and height property for your Parent Widget. It is necessary to define width and height property for ListView or GridView... instead of using SizedBox change it to Container... then in constraints property you can define your sizes. For good code standard always use Min/Max width and height

Example code :

Container(
          constraints: BoxConstraints( //below mentioned sizes for reference only
                    minWidth: 100.0,
                    maxWidth: 320.0, 
                    minHeight: 100.0,
                    maxHeight: 600.0),
          child: GridView.builder(
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              childAspectRatio: MediaQuery.of(ctx).size.width /
                  (MediaQuery.of(ctx).size.height / 4),
              crossAxisCount: MediaQuery
                  .of(ctx)
                  .size
                  .width > 600 ? 3 : 1,
            ),
            itemCount: content.length,
            itemBuilder: (BuildContext ctx, index) {
              return SizedBox(
                height: 100,
                width: 300,
                child: ListTile(
                  leading: content[index]["icon"],
                  title: content[index]["title"],
                  subtitle: Expanded(
                    child: Text(
                      content[index]["text"],
                      style: const TextStyle(fontSize: 18),
                    ),
                  ),
                ),
              );
            },
          ),
        );

0
Bymolda On

Maybe you could wrap it inside a column and use flexible or expanded widgets to set the proportion for the GridView and other childs.

Column(
        children: [
        Flexible(
          flex: 1,
          child: SizedBox(
            // height: 400,
            child: GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                childAspectRatio: MediaQuery.of(ctx).size.width /
                    (MediaQuery.of(ctx).size.height / 4),
                crossAxisCount:
                    MediaQuery.of(ctx).size.width > 600 ? 3 : 1,
              ),
              itemCount: content.length,
              itemBuilder: (BuildContext ctx, index) {
                return SizedBox(
                  height: 100,
                  width: 300,
                  child: ListTile(
                    leading: content[index]["icon"],
                    title: content[index]["title"],
                    subtitle: Expanded(
                      child: Text(
                        content[index]["text"],
                        style: const TextStyle(fontSize: 18),
                      ),
                    ),
                  ),
                );
              },
            ),
          ),
        ),//Other childs
        Flexible(
          flex: 3,
          child: SizedBox(
            child: Container(
              color: Colors.red,
            ),
          ),
        )
      ],
    ),