Piercarlo Slavazza
Piercarlo Slavazza

Reputation: 487

How to implement in Flutter a staggered grid view?

I would like to implement in Flutter a Staggered Grid view - such as the Pinterest staggered grid view (which used to be implemented via their own Android Widget, and now via the Google's StaggeredGridLayoutManager).

So the requirements are:

I know there is a plugin which is named flutter_staggered_grid_view, but this is of no use because it requires to know in advance the precise height of each tile of the grid - which of course it is not my case.

Upvotes: 21

Views: 43938

Answers (5)

AL MAMUN
AL MAMUN

Reputation: 396

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view.dart';

class HomePage extends StatelessWidget {
final List<String> images = [
"https://uae.microless.com/cdn/no_image.jpg",
"https://images-na.ssl-images-amazon.com/images/I/81aF3Ob-2KL._UX679_.jpg",
"https://www.boostmobile.com/content/dam/boostmobile/en/products/phones/apple/iphone-7/silver/device-front.png.transform/pdpCarousel/image.jpg",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgUgs8_kmuhScsx-J01d8fA1mhlCR5-1jyvMYxqCB8h3LCqcgl9Q",
"https://ae01.alicdn.com/kf/HTB11tA5aiAKL1JjSZFoq6ygCFXaw/Unlocked-Samsung-GALAXY-S2-I9100-Mobile-Phone-Android-Wi-Fi-GPS-8-0MP-camera-Core-4.jpg_640x640.jpg",
"https://media.ed.edmunds-media.com/gmc/sierra-3500hd/2018/td/2018_gmc_sierra-3500hd_f34_td_411183_1600.jpg",
"https://hips.hearstapps.com/amv-prod-cad-assets.s3.amazonaws.com/images/16q1/665019/2016-chevrolet-silverado-2500hd-high-country-diesel-test-review-car-and-driver-photo-665520-s-original.jpg",
"https://www.galeanasvandykedodge.net/assets/stock/ColorMatched_01/White/640/cc_2018DOV170002_01_640/cc_2018DOV170002_01_640_PSC.jpg",
"https://media.onthemarket.com/properties/6191869/797156548/composite.jpg",
"https://media.onthemarket.com/properties/6191840/797152761/composite.jpg",
];

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      elevation: 0,
      backgroundColor: Colors.transparent,
      leading: Icon(
        Icons.arrow_back_ios,
        color: Colors.black,
      ),
      actions: [
        IconButton(
          onPressed: () {},
          icon: Icon(
            Icons.shopping_cart,
            color: Colors.black,
          ),
        )
      ],
    ),
    body: Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(16.0),
          child: Row(
            children: [
              Expanded(
                child: Text(
                  "ShopX",
                  style: TextStyle(
                    fontFamily: 'avenir',
                    fontSize: 32,
                    fontWeight: FontWeight.w900,
                  ),
                ),
              ),
              IconButton(
                onPressed: () {},
                icon: Icon(Icons.view_list_rounded),
              ),
              IconButton(
                onPressed: () {},
                icon: Icon(Icons.grid_view),
              ),
            ],
          ),
        ),
        Expanded(
          child: StaggeredGridView.countBuilder(
            crossAxisCount: 2,
            itemCount: images.length,
            mainAxisSpacing: 4.0,
            crossAxisSpacing: 4.0,
            itemBuilder: (context, index) {
              return Container(
                child: Card(
                  child: Column(
                    children: [
                      Image.network(images[index]),
                      Text("Some Text"),
                    ],
                  ),
                ),
              );
            },
            staggeredTileBuilder: (index) => StaggeredTile.fit(1),
          ),
        ),
      ],
    ),
  );
}

Try Your Result

Upvotes: 2

Blasanka
Blasanka

Reputation: 22437

As Romain Rastler said, StaggeredGridView is great solution and he is updating it regularly, below is an example, I have built to get different height grid view when we are fetching content from internet(you can apply to a API):

First of all add this dependency (currently its version is 0.3.0)

pubspec.yaml : flutter_staggered_grid_view: 0.3.0

then import this : import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

import 'package:flutter/material.dart';

import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';

class StaggeredGridExample extends StatefulWidget {
  @override
  _StaggeredGridExampleState createState() => _StaggeredGridExampleState();
}

class _StaggeredGridExampleState extends State<StaggeredGridExample> {
  final List<String> images = [
    "https://uae.microless.com/cdn/no_image.jpg",
    "https://images-na.ssl-images-amazon.com/images/I/81aF3Ob-2KL._UX679_.jpg",
    "https://www.boostmobile.com/content/dam/boostmobile/en/products/phones/apple/iphone-7/silver/device-front.png.transform/pdpCarousel/image.jpg",
    "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSgUgs8_kmuhScsx-J01d8fA1mhlCR5-1jyvMYxqCB8h3LCqcgl9Q",
    "https://ae01.alicdn.com/kf/HTB11tA5aiAKL1JjSZFoq6ygCFXaw/Unlocked-Samsung-GALAXY-S2-I9100-Mobile-Phone-Android-Wi-Fi-GPS-8-0MP-camera-Core-4.jpg_640x640.jpg",
    "https://media.ed.edmunds-media.com/gmc/sierra-3500hd/2018/td/2018_gmc_sierra-3500hd_f34_td_411183_1600.jpg",
    "https://hips.hearstapps.com/amv-prod-cad-assets.s3.amazonaws.com/images/16q1/665019/2016-chevrolet-silverado-2500hd-high-country-diesel-test-review-car-and-driver-photo-665520-s-original.jpg",
    "https://www.galeanasvandykedodge.net/assets/stock/ColorMatched_01/White/640/cc_2018DOV170002_01_640/cc_2018DOV170002_01_640_PSC.jpg",
    "https://media.onthemarket.com/properties/6191869/797156548/composite.jpg",
    "https://media.onthemarket.com/properties/6191840/797152761/composite.jpg",
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StaggeredGridView.countBuilder(
        crossAxisCount: 4,
        itemCount: images.length,
        itemBuilder: (BuildContext context, int index) => Card(
          child: Column(
            children: <Widget>[
              Image.network(images[index]),
              Text("Some text"),
            ],
          ),
        ),
        staggeredTileBuilder: (int index) =>
        new StaggeredTile.fit(2),
        mainAxisSpacing: 4.0,
        crossAxisSpacing: 4.0,
      ),
    );
  }
}

Upvotes: 13

Vinoth Kumar
Vinoth Kumar

Reputation: 13431

Try this.

return new StreamBuilder<QuerySnapshot>(
      stream: Firestore.instance.collection(PRODUCTS_COLLECTION).snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (!snapshot.hasData) return new Center(child: new CircularProgressIndicator());
        return new StaggeredGridView.count(
          physics: new BouncingScrollPhysics(),
          crossAxisCount: 2,
          children: buildGrid(snapshot.data.documents), 
          staggeredTiles: generateRandomTiles(snapshot.data.documents.length),
        );
      },
    );

List<Widget> buildGrid(List<DocumentSnapshot> documents) {
  List<Widget> _gridItems = [];
  _products.clear();

  for (DocumentSnapshot document in documents) {
    _products.add(Product.fromDocument(document));
  }

  for (Product product in _products) {
    _gridItems.add(buildGridItem(product));
  }

  return _gridItems;
}

Widget buildGridItem(Product product) {
  return new GestureDetector(
    child: new Card(
      elevation: 2.0,
      margin: const EdgeInsets.all(5.0),
      child: new Stack(
        alignment: Alignment.center,
        children: <Widget>[
          new Hero(
            tag: product.name,
            child: new Image.network(product.imageUrl, fit: BoxFit.cover),
          ),
          new Align(
            child: new Container(
              padding: const EdgeInsets.all(6.0),
              child: new Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  new Text('\u20B9 ${product.price}',
                      style: new TextStyle(
                          color: Colors.white,
                          fontWeight: FontWeight.bold,
                          fontSize: 16.0)),
                  new Text(product.name,
                      style: new TextStyle(color: Colors.white)),
                ],
              ),
              color: Colors.black.withOpacity(0.4),
              width: double.infinity,
            ),
            alignment: Alignment.bottomCenter,
          ),
        ],
      ),
    ),
    onTap: () async {
      // TODO
    },
  );
}

List<StaggeredTile> generateRandomTiles(int count) {
  Random rnd = new Random();
  List<StaggeredTile> _staggeredTiles = [];
  for (int i=0; i<count; i++) {
    num mainAxisCellCount = 0;
    double temp = rnd.nextDouble();

    if (temp > 0.6) {
      mainAxisCellCount = temp + 0.5;
    } else if (temp < 0.3) {
      mainAxisCellCount = temp + 0.9;
    } else {
      mainAxisCellCount = temp + 0.7;
    }
    _staggeredTiles.add(new StaggeredTile.count(rnd.nextInt(1) + 1, mainAxisCellCount));
  }
  return _staggeredTiles;
}

Upvotes: 3

Romain Rastel
Romain Rastel

Reputation: 5612

I've updated the flutter_staggered_grid_view package.

Now you can add tiles that fit their content size like this:

tile fit content

You have to create tiles using the StaggeredTile.fit(this.crossAxisCellCount) constructor to do it.

Hope it helps.

Upvotes: 34

Ajay
Ajay

Reputation: 16300

Try this Flutter Staggered Grid View 0.1.4.

demo

Hope it Helps.

Upvotes: 0

Related Questions