Ahmet Balaman LogoAhmet Balaman

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.

Comments