Flutter: GridView Widget Usage
personAhmet Balaman
calendar_today
FlutterGridViewWidgetUIGridLayout
GridView is a widget used in Flutter to create items arranged side by side or stacked in rows. It's ideal for gallery views, product listings, and card-based interfaces.
Live Demo
You can try this widget in the interactive example below:
💡 If the example above doesn't load, click DartPad to run it in a new tab.
Basic Usage - GridView.count
Creating a grid by specifying the column count:
GridView.count(
crossAxisCount: 2, // 2 columns
children: [
Container(color: Colors.red, child: Center(child: Text('1'))),
Container(color: Colors.green, child: Center(child: Text('2'))),
Container(color: Colors.blue, child: Center(child: Text('3'))),
Container(color: Colors.orange, child: Center(child: Text('4'))),
],
)Important Properties
| Property | Description |
|---|---|
crossAxisCount |
Number of columns |
mainAxisSpacing |
Vertical spacing |
crossAxisSpacing |
Horizontal spacing |
childAspectRatio |
Child aspect ratio |
padding |
Outer padding |
scrollDirection |
Scroll direction |
GridView.extent with Maximum Width
Creating a grid by specifying the maximum width for each item:
GridView.extent(
maxCrossAxisExtent: 150, // Each item is maximum 150 pixels wide
mainAxisSpacing: 8,
crossAxisSpacing: 8,
padding: EdgeInsets.all(8),
children: [
Container(color: Colors.purple, child: Center(child: Text('A'))),
Container(color: Colors.pink, child: Center(child: Text('B'))),
Container(color: Colors.cyan, child: Center(child: Text('C'))),
Container(color: Colors.amber, child: Center(child: Text('D'))),
],
)Dynamic Grid with GridView.builder
The .builder subclass is used for dynamic grid creation. It provides a performant solution for large datasets:
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 8,
crossAxisSpacing: 8,
),
itemCount: 20,
padding: EdgeInsets.all(8),
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.primaries[index % Colors.primaries.length],
borderRadius: BorderRadius.circular(8),
),
child: Center(
child: Text(
'${index + 1}',
style: TextStyle(color: Colors.white, fontSize: 24),
),
),
);
},
)SliverGridDelegateWithMaxCrossAxisExtent
Dynamic grid with maximum width:
GridView.builder(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 1.5,
),
itemCount: 12,
itemBuilder: (context, index) {
return Card(
color: Colors.teal.shade100,
child: Center(child: Text('Item $index')),
);
},
)Custom Designed Grid Cards
final List<Map<String, dynamic>> products = [
{'name': 'Product 1', 'price': '\$99', 'icon': Icons.phone_android},
{'name': 'Product 2', 'price': '\$149', 'icon': Icons.laptop},
{'name': 'Product 3', 'price': '\$299', 'icon': Icons.watch},
{'name': 'Product 4', 'price': '\$79', 'icon': Icons.headphones},
];
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 12,
crossAxisSpacing: 12,
childAspectRatio: 0.8,
),
padding: EdgeInsets.all(16),
itemCount: products.length,
itemBuilder: (context, index) {
final product = products[index];
return Card(
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(product['icon'], size: 48, color: Colors.blue),
SizedBox(height: 12),
Text(
product['name'],
style: TextStyle(fontWeight: FontWeight.bold),
),
SizedBox(height: 4),
Text(
product['price'],
style: TextStyle(color: Colors.green, fontSize: 18),
),
SizedBox(height: 8),
ElevatedButton(
onPressed: () {},
child: Text('Buy Now'),
),
],
),
);
},
)Image Grid (Gallery)
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
),
itemCount: 30,
itemBuilder: (context, index) {
return Image.network(
'https://picsum.photos/200?random=$index',
fit: BoxFit.cover,
);
},
)Using childAspectRatio
Adjusting the aspect ratio of items:
GridView.count(
crossAxisCount: 2,
childAspectRatio: 16 / 9, // Wide cards
mainAxisSpacing: 8,
crossAxisSpacing: 8,
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.green),
Container(color: Colors.orange),
],
)Scroll Control
final ScrollController _scrollController = ScrollController();
GridView.builder(
controller: _scrollController,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: 50,
itemBuilder: (context, index) {
return Card(child: Center(child: Text('$index')));
},
)
// Scroll grid to top
_scrollController.animateTo(
0,
duration: Duration(milliseconds: 500),
curve: Curves.easeInOut,
);Summary
- GridView.count: Grid with fixed column count
- GridView.extent: Grid with maximum width
- GridView.builder: Dynamic and performant grid
- SliverGridDelegate: Grid layout control
- childAspectRatio: Item aspect ratio
- mainAxisSpacing / crossAxisSpacing: Spacing settings
GridView is an excellent widget for gallery views and card-based lists.