flutter
/

Flutter GridView Widget Tutorial for Beginners

Last Sync: Today

On this page

9
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Flutter GridView Widget Tutorial for Beginners

What is GridView in Flutter?

GridView is a scrollable, 2D array of widgets. It arranges its children in a grid format – rows and columns – and automatically scrolls when the content exceeds the viewport. GridView is perfect for displaying collections of images, product catalogs, photo galleries, and any other content that benefits from a grid layout.

Basic Usage

The easiest way to create a grid is with GridView.count(), which lets you specify a fixed number of tiles in the cross axis (e.g., columns). Here's a simple example:

DARTRead-only
1
GridView.count(
  crossAxisCount: 2,
  children: List.generate(10, (index) {
    return Card(
      color: Colors.primaries[index % Colors.primaries.length],
      child: Center(child: Text('Item $index')),
    );
  }),
)

This creates a grid with 2 columns and 10 items. The grid scrolls vertically to show all items.

GridView Constructors

Flutter provides several constructors for different use cases:

  • GridView.count – Creates a grid with a fixed number of tiles in the cross axis. Most commonly used for simple grids with a known column count.
  • GridView.extent – Creates a grid where tiles have a maximum cross-axis extent (e.g., max tile width). The number of columns is calculated automatically based on available space.
  • GridView.builder – Creates a scrollable, reactive grid that builds children on demand. Perfect for large or infinite grids (like a photo gallery loaded from the web).
  • GridView.custom – Offers maximum flexibility by letting you provide your own SliverGridDelegate and ChildDelegate.
DARTRead-only
1
// Using GridView.extent – tiles have a maximum width of 150
GridView.extent(
  maxCrossAxisExtent: 150,
  children: [/* ... */],
)

// Using GridView.builder – efficient for large lists
GridView.builder(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
    childAspectRatio: 2.0,
  ),
  itemCount: 100,
  itemBuilder: (context, index) {
    return Container(color: Colors.blue, child: Center(child: Text('$index')));
  },
)

Key Properties

Both GridView.count and GridView.extent are convenience wrappers around a SliverGridDelegate. The core properties you'll work with are:

  • crossAxisCount (for count constructor): The number of columns (vertical grid) or rows (horizontal grid).
  • maxCrossAxisExtent (for extent constructor): The maximum size each tile can take in the cross axis. The grid will fit as many tiles as possible respecting this limit.
  • childAspectRatio: The ratio of the cross-axis to the main-axis extent of each child. For example, a ratio of 2.0 means the child is twice as wide as it is tall (for vertical grids). Defaults to 1.0.
  • mainAxisSpacing: Space between children along the main axis (vertical for vertical grids).
  • crossAxisSpacing: Space between children along the cross axis (horizontal for vertical grids).
  • scrollDirection: Axis.vertical (default) or Axis.horizontal.
  • reverse: Whether the grid scrolls in the reverse direction.
  • shrinkWrap: If true, the grid sizes itself to fit its content (useful inside a Column). Defaults to false.
  • physics: Determines scrolling behavior.

Controlling Child Sizes with Aspect Ratio

The childAspectRatio property is crucial for making your grid look consistent. It defines the ratio of width to height of each grid tile. For example, if you have a vertical grid with crossAxisCount: 3 and you want each tile to be square, set childAspectRatio: 1.0. If you want them to be twice as wide as tall (landscape rectangles), use 2.0.

DARTRead-only
1
GridView.count(
  crossAxisCount: 3,
  childAspectRatio: 1.5, // width / height = 1.5
  children: [/* ... */],
)

Responsive Grids

To create a grid that adapts to screen size, you can use LayoutBuilder or MediaQuery to dynamically adjust crossAxisCount or maxCrossAxisExtent. For example, you might want 2 columns on a phone and 4 on a tablet.

DARTRead-only
1
LayoutBuilder(
  builder: (context, constraints) {
    double width = constraints.maxWidth;
    int columns = (width / 150).floor(); // approximate number of 150px-wide tiles
    return GridView.builder(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: columns,
        childAspectRatio: 1.0,
      ),
      itemCount: 50,
      itemBuilder: (context, index) => Container(color: Colors.amber),
    );
  },
)

Common Mistakes Beginners Make

  • Forgetting to constrain the height: When placing a GridView inside a Column without shrinkWrap: true or wrapping it with Expanded, you'll get an unbounded height error. Always either use Expanded or set shrinkWrap: true (and consider physics: NeverScrollableScrollPhysics() if needed).
  • Using the wrong constructor for large data sets: Using the default GridView constructor with a long list of children can hurt performance. Use GridView.builder for dynamic or large lists.
  • Ignoring childAspectRatio: Without setting this, tiles may look squashed or stretched. Always adjust it to match your content's intended shape.
  • Overlooking spacing: mainAxisSpacing and crossAxisSpacing default to zero, which can make the grid feel cramped. Add a little spacing for visual comfort.
  • Not handling scroll direction: When using a horizontal grid, remember that crossAxisCount then refers to rows, and you need to give the grid a fixed height (e.g., using SizedBox).

Key Points to Remember

  • Use GridView.count when you know the number of columns/rows.
  • Use GridView.extent when you know the desired tile size and want the grid to auto‑fit.
  • Always use GridView.builder for large or infinite lists.
  • Set childAspectRatio to match your tile's width/height proportions.
  • In vertical grids, crossAxisCount = number of columns; in horizontal grids, it = number of rows.
  • For grids inside unbounded containers (like Column), set shrinkWrap: true or wrap with Expanded.

Common Interview Questions

  1. What's the difference between GridView.count and GridView.extent? When would you use each?
  2. How does childAspectRatio affect the layout? Give an example.
  3. How would you create a responsive grid that shows 2 columns on mobile and 4 on tablet?
  4. Explain why you might need shrinkWrap when using GridView inside a Column.
  5. What performance considerations should you keep in mind when building a grid with thousands of items?
  6. How can you create a horizontal grid with a fixed height?

Try it yourself

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('GridView Example')),
        body: GridView.count(
          crossAxisCount: 3,
          crossAxisSpacing: 8,
          mainAxisSpacing: 8,
          childAspectRatio: 1.2,
          children: List.generate(20, (index) {
            return Container(
              color: Colors.primaries[index % Colors.primaries.length],
              child: Center(
                child: Text(
                  'Item $index',
                  style: TextStyle(color: Colors.white, fontSize: 18),
                ),
              ),
            );
          }),
        ),
      ),
    ),
  );
}

Test Your Knowledge

Q1
of 3

Which GridView constructor would you use to create a grid where each tile has a maximum width of 200 pixels?

A
GridView.count(crossAxisCount: 2)
B
GridView.extent(maxCrossAxisExtent: 200)
C
GridView.builder()
D
GridView.custom()
Q2
of 3

What does the `childAspectRatio` property control?

A
The number of columns in the grid
B
The spacing between children
C
The ratio of cross-axis to main-axis size of each child
D
Whether the grid scrolls horizontally or vertically
Q3
of 3

If you put a GridView inside a Column without wrapping it with Expanded or setting shrinkWrap: true, what error might you encounter?

A
RenderFlex overflow error
B
GridView has unbounded height error
C
Missing constraints error
D
No error, it works fine

Previous

flutter listview

Next

flutter padding

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.