Reputation: 3663
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]));
});
Upvotes: 10
Views: 9992
Reputation: 10344
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
.
Upvotes: 5