Skip to main content

flutter_staggered_grid_view 0.8.0-dev.3 copy "flutter_staggered_grid_view: ^0.8.0-dev.3" to clipboard
flutter_staggered_grid_view: ^0.8.0-dev.3 copied to clipboard

Provides a collection of Flutter grids layouts (staggered, masonry, quilted, woven, etc.).

Pub BuyMeACoffee

flutter_staggered_grid_view #

Provides a collection of Flutter grids layouts.

Getting started #

In the pubspec.yaml of your flutter project, add the following dependency:

dependencies:
  ...
  flutter_staggered_grid_view: <latest_version>

In your library add the following import:

import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

For help getting started with Flutter, view the online documentation.

Layouts #

This package contains various grid layouts. In the following section, you'll discover each one of them. The explanation of the layout will always considered a top-to-bottom and left-to-right directions to simplify the description. However it is possible to change these directions in the code.

In the examples below, Tile is not part of the package: it's a simple widget of the example app, which you can replace with your own widgets. The example app shows each layout in action.

Staggered #

Staggered Grid Layout

This layout is intended for a small number of items. I didn't find, for the moment, a performant algorithm which would work in a Sliver context, that's why this is not a GridView and therefore there are no SliverStaggeredGrid.

Grid properties

  • Evenly divided in n columns
  • Small number of items
  • Not scrollable

Tile properties

  • Must occupy 1 to n columns
  • Its main axis extent can be:
    • a number of cells, which can be fractional, with StaggeredGridTile.count;
    • a fixed extent, with StaggeredGridTile.extent;
    • the extent of its content, with StaggeredGridTile.fit.

Placement algorithm

  • Top-most and then left-most (StaggeredGridPlacement.dense, the default): a tile can fill a hole left before a previous tile, so the tiles may not appear in their order.
  • With placement: StaggeredGridPlacement.sparse, each tile is placed after the previous one, in the reading order: the tiles appear in their order, and the holes are left empty.

Example

Below you'll find the code to create this grid layout:

Staggered example

StaggeredGrid.count(
  crossAxisCount: 4,
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  children: const [
    StaggeredGridTile.count(
      crossAxisCellCount: 2,
      mainAxisCellCount: 2,
      child: Tile(index: 0),
    ),
    StaggeredGridTile.count(
      crossAxisCellCount: 2,
      mainAxisCellCount: 1,
      child: Tile(index: 1),
    ),
    StaggeredGridTile.count(
      crossAxisCellCount: 1,
      mainAxisCellCount: 1,
      child: Tile(index: 2),
    ),
    StaggeredGridTile.count(
      crossAxisCellCount: 1,
      mainAxisCellCount: 1,
      child: Tile(index: 3),
    ),
    StaggeredGridTile.count(
      crossAxisCellCount: 4,
      mainAxisCellCount: 2,
      child: Tile(index: 4),
    ),
  ],
);

The cells are square. For tiles with another aspect ratio, use StaggeredGridTile.fit with an AspectRatio:

StaggeredGridTile.fit(
  crossAxisCellCount: 1,
  child: AspectRatio(
    aspectRatio: 9 / 16,
    child: Tile(index: 5),
  ),
),

Masonry #

Masonry Grid Layout

This layout facilitates the browsing of uncropped peer content. Container heights are sized based on the widget size.

This is a complete separate grid and not a SliverGridDelegate for performance reasons. The SliverGrid is great but it needs to have a layout which does not depends on the size of its children. Otherwise we have to compute the size to all children before the end of the cache, which is really not performant for a masonry layout.

Grid properties

  • Evenly divided in n columns

Tile properties

  • Must occupy 1 column only

Placement algorithm

  • Top-most and then left-most

Example

Below you'll find the code to create this grid layout:

Masonry example

MasonryGridView.count(
  crossAxisCount: 4,
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  itemBuilder: (context, index) {
    return Tile(
      index: index,
      extent: (index % 5 + 1) * 100,
    );
  },
);

Known extents

The position of a child depends on the size of all the children before it, so by default the grid has to build every child once to place it. If you already know the size of the children (for example the aspect ratio of images returned by an API), provide a mainAxisExtentBuilder. The children are then placed without being built: jumping far in the grid or changing the number of columns only builds the visible children, and the scroll extent is exact from the start.

MasonryGridView.count(
  crossAxisCount: 3,
  itemCount: photos.length,
  // crossAxisExtent is the width of a column.
  mainAxisExtentBuilder: (index, crossAxisExtent) =>
      crossAxisExtent / photos[index].aspectRatio,
  itemBuilder: (context, index) => Image.network(photos[index].url),
);

Each child is forced to have the returned extent. Return null if the index is greater than the index of the last child. When itemCount is provided, it prevails: the builder is not called for indexes after it.

Full span children

A child can span the whole cross axis, for example a banner or a section header, with isFullSpan. It starts below all the columns, and the columns are aligned after it.

MasonryGridView.count(
  crossAxisCount: 2,
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  itemCount: 100,
  // A banner every 10 children.
  isFullSpan: (index) => index % 10 == 9,
  itemBuilder: (context, index) {
    return Tile(
      index: index,
      extent: index % 10 == 9 ? 80 : (index % 5 + 1) * 100,
    );
  },
);

Since a full span child starts after the longest column, some space can be left empty at the end of the shorter ones.

Sliver

To combine a masonry grid with other slivers (an app bar, a header, another grid...) in a CustomScrollView, use SliverMasonryGrid:

CustomScrollView(
  slivers: [
    const SliverAppBar(title: Text('Masonry')),
    SliverMasonryGrid.count(
      crossAxisCount: 4,
      mainAxisSpacing: 4,
      crossAxisSpacing: 4,
      childCount: 100,
      itemBuilder: (context, index) {
        return Tile(
          index: index,
          extent: (index % 5 + 1) * 100,
        );
      },
    ),
  ],
);

Quilted #

Quilted Grid Layout

This layout emphasizes certain items over others in a collection. It creates hierarchy using varied container sizes and ratios.

This is a specific delegate for the built-in GridView (or SliverGrid) widget. That's why the example below will create such a layout with a GridView.

Grid properties

  • Evenly divided in n columns
  • The height of each row is equal to the width of each column
  • A pattern defines the size of the tiles and different mode of repetition are possible

Tile properties

  • Must occupy 1 to n columns
  • Must occupy 1 or more entire rows

Placement algorithm

  • Top-most and then left-most

Example

Below you'll find the code to create this grid layout:

Quilted example

GridView.custom(
  gridDelegate: SliverQuiltedGridDelegate(
    crossAxisCount: 4,
    mainAxisSpacing: 4,
    crossAxisSpacing: 4,
    repeatPattern: QuiltedGridRepeatPattern.inverted,
    pattern: [
      QuiltedGridTile(2, 2),
      QuiltedGridTile(1, 1),
      QuiltedGridTile(1, 1),
      QuiltedGridTile(1, 2),
    ],
  ),
  childrenDelegate: SliverChildBuilderDelegate(
    (context, index) => Tile(index: index),
  ),
);

Woven #

Woven Grid Layout

This layout facilitates the browsing of peer content. The items are displayed in containers of varying ratios to create a rhythmic layout.

This is a specific delegate for the built-in GridView (or SliverGrid) widget. That's why the example below will create such a layout with a GridView.

Grid properties

  • Evenly divided in n columns
  • The height the rows is the maximum height of the tiles
  • A pattern defines the size of the tiles
  • The size of the tiles follows the pattern in a 'z' sequence.

Tile properties

  • The height is defined by an aspectRatio (width/height)
  • The width is defined by a crossAxisRatio (width/column's width) between 0 (exclusive) and 1 (inclusive)
  • Each tile can define how it is aligned within the available space

Placement algorithm

  • Top-most and then left-most

Example

Below you'll find the code to create this grid layout:

Woven example

GridView.custom(
  gridDelegate: SliverWovenGridDelegate.count(
    crossAxisCount: 2,
    mainAxisSpacing: 8,
    crossAxisSpacing: 8,
    pattern: [
      WovenGridTile(1),
      WovenGridTile(
        5 / 7,
        crossAxisRatio: 0.9,
        alignment: AlignmentDirectional.centerEnd,
      ),
    ],
  ),
  childrenDelegate: SliverChildBuilderDelegate(
    (context, index) => Tile(index: index),
  ),
);

Staired #

Staired Grid Layout

This layout uses alternating container sizes and ratios to create a rhythmic effect. It's another kind of woven grid layout.

This is a specific delegate for the built-in GridView (or SliverGrid) widget. That's why the example below will create such a layout with a GridView.

Grid properties

  • A pattern defines the size of the tiles
  • Each tile is shifted from the previous one by a margin in both axis
  • The tracks of the pattern go back and forth, like stairs ('S' sequence), unless alternateDirections is false ('Z' sequence)

Tile properties

  • The height is defined by an aspectRatio (width/height)
  • The width is defined by a crossAxisRatio (width/available horizontal space) between 0 (exclusive) and 1 (inclusive)

Placement algorithm

  • In an 'S' sequence by default: from left to right, then from right to left, and so on
  • In a 'Z' sequence with alternateDirections: false: all the tracks from left to right

Example

Below you'll find the code to create this grid layout:

Staired example

GridView.custom(
  gridDelegate: SliverStairedGridDelegate(
    crossAxisSpacing: 48,
    mainAxisSpacing: 24,
    startCrossAxisDirectionReversed: true,
    pattern: [
      StairedGridTile(0.5, 1),
      StairedGridTile(0.5, 3 / 4),
      StairedGridTile(1.0, 10 / 4),
    ],
  ),
  childrenDelegate: SliverChildBuilderDelegate(
    (context, index) => Tile(index: index),
  ),
);

Aligned #

Aligned Grid Layout

This layout is also called CSS Grid. This is a common grid layout on the web, where each item within a track has the maximum cross axis extent of its siblings.

Grid properties

  • Evenly divided in n columns
  • The rows can have differents heights

Tile properties

  • Must occupy 1 column only
  • Each tile has the same height as the tallest one of the row.

Placement algorithm

  • Top-most and then left-most

Example

Below you'll find the code to create this grid layout:

Aligned example

AlignedGridView.count(
  crossAxisCount: 4,
  mainAxisSpacing: 4,
  crossAxisSpacing: 4,
  itemBuilder: (context, index) {
    return Tile(
      index: index,
      extent: (index % 7 + 1) * 30,
    );
  },
);

Sliver

To combine an aligned grid with other slivers in a CustomScrollView, use SliverAlignedGrid:

CustomScrollView(
  slivers: [
    const SliverAppBar(title: Text('Aligned')),
    SliverAlignedGrid.count(
      crossAxisCount: 4,
      mainAxisSpacing: 4,
      crossAxisSpacing: 4,
      itemCount: 100,
      itemBuilder: (context, index) {
        return Tile(
          index: index,
          extent: (index % 7 + 1) * 30,
        );
      },
    ),
  ],
);

Sponsoring #

I'm working on my packages on my free-time, but I don't have as much time as I would. If this package or any other package I created is helping you, please consider to sponsor me so that I can take time to read the issues, fix bugs, merge pull requests and add features to these packages.

Sponsors #

I want to thank Tommy for sponsoring this package. Thanks to him, I took the time to investigate in the previous performance issues and refactor this library to make it how is it today.


Tom3652

Contributions #

Feel free to contribute to this project.

If you find a bug or want a feature, but don't know how to fix/implement it, please fill an issue.
If you fixed a bug or implemented a feature, please send a pull request.

4.78k
likes
160
points
1.43M
downloads

Documentation

API reference

Publisher

verified publisherromainrastel.com

Weekly Downloads

Provides a collection of Flutter grids layouts (staggered, masonry, quilted, woven, etc.).

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_staggered_grid_view