Proper method for setting childAspectRatio in flutter

6,335

DISCLAIMER: This is theoretical explanation of how GridView works. Proposed solution is not designed for heavy content. Use GridView theory that I describe here to build layout that you desire.

Let me start with crossAxisCount, which is supposed to be interpreted as a number of columns in a table.

e.g. crossAxisCount: 3,

|  cell-1  ||  cell-2  ||  cell-3  |
------------------------------------ // new row after every 3 cells
|  cell-4  ||  cell-5  ||  cell-6  |

What flutter does with crossAxisCount: N, is tries to fit exactly N number of cells in a row. Hence, width of one individual cell will equal grid width divided by N.

e.g. crossAxisCount: 3, -> cellWidth = parentWidth / 3 (pseudocode)


Now, what happens next is calculation of cell's height using childAspectRatio that your initial question is about.

e.g. cellWidth = parentWidth / crossAxisCount & cellHeight = cellWidth / childAspectRatio.

This way, you should interpret childAspectRatio as a ratio of every individual cell's width to its height (and vice versa).


I assume you noticed that GridView is rather limited when it comes to unusually structured layout.

In case you truly think that GridView is not enough for what you are trying to build - I'd recommend using other widgets that support multiple children layout. For instance, I use Wrap widget to display very fluid content, in which every element has its own dynamic width & height.

I am not aware of what type of layout you need, but in case of a very dynamic / fluid yet light concept you can try using Wrap:

@override
Widget build(BuildContext context) {
  final mediaQuery = MediaQuery.of(context);
  return SingleChildScrollView(
    child: Wrap(
      children: List.generate(totalItemsToDisplay, (index) {
        final cellWidth = mediaQuery.size.width / 3; // Every cell's `width` will be set to 1/3 of the screen width.
        return SizedBox(
          width: cellWidth,
          // You can either use some static number for `height`, or set ratio to cellWidth.
          // Setting `height` to `null` should work too, which would make height of a cell auto-resizable according to its content.
          height: 123,
          child: ...,
        );
      })
    )
  );
}

However, I would not recommend using this to display large sets of data.

If your goal is to display a set of posts / articles / pictures etc., something that initially implies structured heavy content - I would recommend going with GridView by standardising cells height through childAspectRatio.

Share:
6,335
Ashwin S Ashok
Author by

Ashwin S Ashok

Android Developer.

Updated on December 11, 2022

Comments

  • Ashwin S Ashok
    Ashwin S Ashok over 1 year

    What is the proper way of calculating childAspectRatio of SliverGridDelegateWithFixedCrossAxisCount in flutter. How to manage the the correct height of each view that is compatible with all devices and should work in landscape and portrait

    GridView.builder(
        physics: BouncingScrollPhysics(),
        padding: const EdgeInsets.all(4.0),
        itemCount: snapshot.data.results.length,
        gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: itemCount,
          childAspectRatio: 0.501,
          mainAxisSpacing: 4.0,
          crossAxisSpacing: 4.0,
        ),
        itemBuilder: (BuildContext context, int index) {
          return GridTile(
              child: _buildGridItem(context, snapshot.data.results[index]));
        });
    
  • Ashwin S Ashok
    Ashwin S Ashok almost 5 years
    How this is standardised cells height through childAspectRatio??
  • Egor Zvonov
    Egor Zvonov almost 5 years
    @AshwinSAshok what I meant is that all cells will have one size, according to childAspectRatio. If you have dynamically sized elements - you might want to use Wrap solution that I proposed.
  • Ashwin S Ashok
    Ashwin S Ashok almost 5 years
    You have already mentioned that " Wrap : I would not recommend using this to display large sets of data." Is there a possible way to calculate the childAspectRatio.