GridView in Flutter

GridView in Flutter is a scrollable, 2D array of widgets that displays a list of items as a grid by combining row and column classes. Also, it’s commonly used to show a list of photos or any other items we want. For example, you can use GridView to display products, images, posts, etc. Not to mention, it can contain any type of widgets including text, icons, images, etc based on the user requirements.

GridView has various types that can be implemented in different cases and scenarios. These types are as the following:

  • GridView.builder
  • GridView.count
  • Gridview.custom
  • GridView.extent

GridView is a more complicated version of ListView as it comes in a tabular form which gives it an interesting and professional look.

In this tutorial, we’ll discuss the 4 types of GridView  as well as a special type of GridView known as Staggered GridView and walk through practical examples to learn the difference between them so you can start implementing GridView in your Flutter applications.

So without further ado, let’s start our tutorial!

Table of Contents

GridView Overview

To begin with, GridView has some common properties that we need to understand in order to implement it correctly. The most important property which is used with all types of GridView is gridDelegate.

1 gridDelegate

a mandatory property which controls how the items within the grid are displayed. There are 2 main types of gridDelegate known as SliverGridDelegateWithFixedCrossAxisCount and SliverGridDelegateWithMaxCrossAxisExtent.
Now, let’s go through each one of them separately

SliverGridDelegateWithFixedCrossAxisCount

This creates a fixed number of tiles in the cross axis. For example, if the grid is vertical, this delegate will create a layout with a fixed number of columns. If the grid is horizontal, this delegate will create a layout with a fixed number of rows. It creates grids with equally sized and spaced tiles.
It has 5 properties which are:

  • crossAxisCount: a required properties that specifies the number of tiles within the grid cross axis (default is horizontal).
  • childAspectRatio: The ratio of the cross-axis to the main-axis extent of each child. In other words, the ratio of the width to the height (width:height)
  • crossAxisSpacing: the space between the children in the cross axis.
  • mainAxisSpacing: the space between the children in the main axis
  • mainAxisExtent: the size of each child in the main axis. It define the logical pixels taken by each tile in the main-axis.
GridView(

  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    childAspectRatio: 1,
    crossAxisSpacing: 16,
    mainAxisSpacing: 16,
    crossAxisCount: 2,

  ),
  
  children: [
    Container(color: Colors.red,),
    Container(color: Colors.blue,),
    Container(color: Colors.yellow,),
    Container(color: Colors.green,),

  ],

),
gridview in flutter

SliverGridDelegateWithMaxCrossAxisExtent

This creates grid layouts with tiles that each have a maximum cross-axis extent with equally sized and spaced tiles. For example, if the grid is vertical with a width of 500 pixels and the maximum cross extent is 150, the delegate will create a grid of 4 columns that are 125 pixels wide.

As a matter of fact, it has similar properties to SliverGridDelegateWithFixedCrossAxisCount but instead of crossAxisCount it has maxCrossAxisExtent

  • maxCrossAxisExtent: specifies the maximum extent (size) of the tile in the cross axis.
GridView(

  gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
    maxCrossAxisExtent: 120,
  ),

  children: [
    Container(color: Colors.red,),
    Container(color: Colors.blue,),
    Container(color: Colors.yellow,),
    Container(color: Colors.green,),

  ],

),
slivergriddelegatewithmaxcrossaxisextent

2 crossAxisSpacing

This is an optional property that defines the number of pixels (space) between the grid children in the cross Axis. Take note that cross axis is determined based on the scroll direction of the grid. By default, the cross axis is the vertical direction of the grid which you can change using the scrollDirection property.

scrollDirection: Axis.vertical,
// or
scrollDirection: Axis.horizontal,

3 crossAxisCount

This is another optional property that specifies the number of widgets in the cross axis (columns by default). You can use this property if you want the grid to display a specific number of widgets within the cross axis.

crossAxisCount: 2

4 mainAxisSpacing

This is a similar property to crossAxisSpacing but it determines the number of pixels between the grid in the main axis (space between rows by default)

mainAxisSpacing: 4.0

GridView.builder

GridView.builder in Flutter creates a scrollable 2D array of widgets on demand. It is suitable for grids with large amount of content as the builder only creates those children who are visible to the user. In other words, GridView.builder creates dynamic widgets using either SliverGridDelegateWithFixedCrossAxisCount or SliverGridDelegateWithMaxCrossAxisExtent. gridView.builder has few special attributes which are:

  •  itemCount: defines the number of children to be displayed within the grid.
  • itemBuuilder: used to create the content of the grid based on the number of widgets specified in itemCount. This is only called when indices is > 0 and < itemCount.

GridView.builder constructor

GridView.builder(

    {Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry? padding,
    required SliverGridDelegate gridDelegate,
    required IndexedWidgetBuilder itemBuilder,
    int? itemCount,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double? cacheExtent,
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge}

)

Example

GridView.builder(
  itemCount: 6,
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 2,
      crossAxisSpacing: 4.0,
      mainAxisSpacing: 4.0
  ),
  itemBuilder: (BuildContext context, int index) {
    return Container(
      color: Colors.red,
      child: Center(
        child: Text(
          (index + 1).toString(),
          style: TextStyle(fontSize: 30),
        ),
      ),
      
    );
  },
)
gridview.builder

GridView.count in Flutter

GridView.count is the mot commonly grid used by Flutter developers and it’s the easiest one to implement. This is because we already know the number of widgets we need to generate. It allows you to create a specific number of columns and rows within the grid. GridView.count has a mandatory property which is crossAxisCount which is as previously mentioned, used to determines the number of widgets within the cross axis (columns). In addition, it is easier to implement as it doesn’t require you to use the gridDelegate property.

GridView.count is commonly used to create a keypad UI as you need a specific number of widgets in both horizontal and vertical directions.

GridView.count constructor

GridView.count(

    {Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry? padding,
    required int crossAxisCount,
    double mainAxisSpacing = 0.0,
    double crossAxisSpacing = 0.0,
    double childAspectRatio = 1.0,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double? cacheExtent,
    List<Widget> children = const <Widget>[],
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge}

)

Example

GridView.count(
    crossAxisCount: 3,
      mainAxisSpacing: 4,
      crossAxisSpacing: 4,
      children: [
        Container(
          color: Colors.red,
          ),
        Container(
          color: Colors.yellow,
        ),
        Container(
          color: Colors.green,
        ),
      ],
      
)
gridview.count

GridView.extent in Flutter

GridView.extent creates a scrollable 2D array of widgets with children that each have a maximum cross-axis extent. It uses SliverGridDelegateWithMaxCrossAxisExtent as its gridDelegate. In other words, it allows you to create widgets with equal size and space. Also, it has a required property which is maxCrossAxisExtent.

GridView.extent constructor

GridView.extent(

    {Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry? padding,
    required double maxCrossAxisExtent,
    double mainAxisSpacing = 0.0,
    double crossAxisSpacing = 0.0,
    double childAspectRatio = 1.0,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double? cacheExtent,
    List<Widget> children = const <Widget>[],
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge}

)

Example

Now in the example below, you’ll notice that only 2 widgets are created in the cross axis. This is because we specified the maxCrossAxisExtent to be 300 therefore the screen size cannot display more than two widgets within the row. If you change the value to be less, for example 100, then more widgets will be displayed within one row.

GridView.extent(
  maxCrossAxisExtent: 300,
  crossAxisSpacing: 4,
  mainAxisSpacing: 4,
  children: [
    Container(
    color: Colors.red,
  ),
    Container(
      color: Colors.yellow,
    ),
    Container(
      color: Colors.green,
    ),
    Container(
      color: Colors.blue,
    ),
    Container(
      color: Colors.deepPurple,
    ),
  ],
)),
gridview.extent

GridView.custom in Flutter

GridView.custom creates a scrollable 2D array of widgets with custom SliverGridDelegate and SliverChildDelegate. It has two required properties which are gridDelegate and childrenDelegate. As previously mentioned, gridDelegate is used to control the arrangement of the widgets within the grid using either SliverGridDelegateWithFixedCrossAxisCount or SliverGridDelegateWithMaxCrossAxisExtent. childrenDelegate is used to create the children for the grid.

GridView.custom constructor

const GridView.custom(

    {Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry? padding,
    required SliverGridDelegate gridDelegate,
    required SliverChildDelegate childrenDelegate,
    double? cacheExtent,
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge}

)

Example

GridView.custom(
        childrenDelegate: SliverChildBuilderDelegate((BuildContext context, int index) {
          return Container(color: Colors.red,);
        },
        childCount: 3
),
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
          crossAxisSpacing: 4,
          mainAxisSpacing: 4,

),

)
gridview.custom

Staggered Grid View

Staggered GridView in flutter creates widgets in varying height and width which gives the grid a unique look by displaying its children in different sizes. This is commonly used to display pictures on social media platforms like Pinterest and phone gallery. In other words, you can have widgets in both portrait and landscape orientation. It has multiple types and layouts such as StaggeredGridView.count, StaggeredGridView.extent, etc.

Now, we’ll only cover StaggeredGridView.countBuilder while we’ll discuss the other types in future posts.

you can consider StaggeredGridView.countBuilder as a mix of the normal GridView.count and GridView.builder with additional feature (the varying tiles sizing). It creates widgets dynamically on demand with a fixed number of tiles within the cross axis in different sizes.

StaggeredGridView.countBuilder properties

  • staggeredTileBuilder: returns a staggeredTile which has several constructors that controls the tiles orientations. These constructors are:
    • StaggeredTile.count : creates the tiles based on the specified number of cells in both cross and main axis.
    • StaggeredTile.fit : creates tile based on its original size.
    • StaggeredTile.extent : creates tiles based on a specific extent (size)
  • crossAxisCount: defines the number of widgets in the cross axis.
  • mainAxisSpacing and crossAxisSpacing: defines the space between the grid children in the main and cross axis.
  • itemCount and itemBuilder: itemCount is to define the number of widgets to generate while itemBuilder is to generate these widgets based on itemCount value.

Example

First of all, you need to add the StaggeredGridView dependency in the pubspec.yaml file and run pub get

flutter_staggered_grid_view: 0.4.1

Next, you need to import the library in the dart file where you’ll create the staggered grid view

import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

Now, we can start implementing the staggered grid view

StaggeredGridView.countBuilder(
    crossAxisCount: 2,
    mainAxisSpacing: 4,
    crossAxisSpacing: 4,
    itemCount: 20,
    padding: EdgeInsets.only(left: 10, right: 10, top: 5),
    itemBuilder: (context, index) {
      return Container(color: index %2 == 0? Colors.lightBlue[300]: Colors.blueGrey,
      child: Center(
        child: Text(index.toString(), style: TextStyle(fontSize: 30, color: Colors.white, fontWeight: FontWeight.bold),
        ),
      ),);
    },
    staggeredTileBuilder: (index) {
      return StaggeredTile.count(1,index.isOdd? 1.5 : 2);
    })
staggered grid view

Conclusion

This brings an end to our interesting tutorial where we learnt all about GridView layout and its various types in addition to Staggered Grid View.

These are some of the essential widgets that every Flutter developer should know about and learn how to implement. Make sure to practice them well and understand how they differ from each other.

If you wish to learn more about Flutter, I have a whole category called Flutter that’s ripe for you to explore. You can learn about Flutter widgets, layouts, onboarding screen, tabbar, inkwell and gesture detector, stepper and practice with a bunch of real examples.

Also, don’t forget to like and share my Facebook page, share the post with those who care to learn, and subscribe to my blog to be one of the firsts to know about my newest posts!

Thank you!

Oh hi there!
It’s nice to meet you.

Sign up to receive awesome content in your inbox, every month.

Let's Do This!

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top