How to link Flutter StaggeredGridView items individually?

Issue

Following a tutorial on StaggeredGridView, I successfully built a page to display staggered grids of text and an icon. The tutorial stopped short on explaining how to link each grid item separately. I am aware of onTap, GestureDetector, OnPressed, but I can not figure out how to implement any of these in this grid layout so that each element can link to a different material page route (or _UrlLauncher, etc.)

child: Material(
child: StaggeredGridView.count(
    crossAxisCount: 2,
    crossAxisSpacing: 8,
    mainAxisSpacing: 16,
    shrinkWrap: true,
    padding: EdgeInsets.symmetric(horizontal: 6.0, vertical: 6.0),
    children: < Widget > [
        MyItems(Icons.shop, "Tecxt Here", 0xff42a5f5),
        MyItems(Icons.shop, "Text Here", 0xff42a5f5),
        MyItems(Icons.shop, "Text Here", 0xff42a5f5),
        MyItems(Icons.shop, "Text Here", 0xff42a5f5),
        MyItems(Icons.shop, "Text Here", 0xff42a5f5),
        MyItems(Icons.shop, "Text Here", 0xff42a5f5),
        MyItems(Icons.shop, "Text Here", 0xff42a5f5),

    ],
    staggeredTiles: [
        StaggeredTile.extent(2, 150.0),
        StaggeredTile.extent(1, 150.0),
        StaggeredTile.extent(1, 150.0),
        StaggeredTile.extent(2, 150.0),
        StaggeredTile.extent(1, 150.0),
        StaggeredTile.extent(1, 150.0),
        StaggeredTile.extent(2, 150.0),
    ],
),

), //material

For each “MyItems” we created a Method and parameters:

  Material MyItems(IconData icon, String heading, int color) {
    return Material(color: Colors.white,
      elevation: 12.0,
      shadowColor: Color(0xff2962ff),
      borderRadius: BorderRadius.circular(20.0),
      child: Center(
        child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: < Widget > [
                    Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: < Widget > [

                            //Text here
                            Padding(
                                padding: const EdgeInsets.all(8.0),
                                child: Text(heading,
                                    style: TextStyle(
                                        color: new Color(color),
                                        fontSize: 20.0,
                                    ),
                                ),
                            ), //text

                            //icon
                            Material(
                                color: new Color(color),
                                borderRadius: BorderRadius.circular(24.0),
                                child: Padding(padding: const EdgeInsets.all(16.0),
                                    child: Icon(
                                        icon,
                                        color: Colors.white,
                                        size: 20.0,

                                    ),
                                ),
                            ),
                        ],
                    ),
                ]))),
    );

There doesn’t appear to be any information on how to solve this. The only follow up I could find from the author was “There are couple of ways to tackle it”:

  1. Use Keys property of the widget

    TagButton(onPressed: (k) => onPress(k)),
    void onPress(Key id) {
    print(‘pressed $id’);
    }

2.Assign a callback that calls a different method for each button

  1. Or you can pass a parameter like shown below and use a switch to identify the parameter value and call the corresponding method.

    onPressed: () => onButtonPressed(‘okButton’),

But after much struggle, I just can’t comprehend this. Is it even possible to individually link each staggered grid to their own unique link (page route, UrlLauncher, etc.?

Solution

You can copy paste run full code below
You can pass route name as String

code snippet

return MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  initialRoute: '/',
  routes: {
    // When navigating to the "/" route, build the FirstScreen widget.
    '/': (context) => Example01(),
    '/first': (context) => FirstScreen(),
    '/second': (context) => SecondScreen(),
  },
);
...

List<Widget> _tiles = const <Widget>[
  const MyItems(Icons.shop, "Text1 Here", 0xff42a5f5, "/first"),
  const _Example01Tile(Colors.green, Icons.widgets),
  const _Example01Tile(Colors.amber, Icons.panorama_wide_angle),
  const MyItems(Icons.shop, "Text 2 Here", 0xff42a5f5, "/second"),
...

 class MyItems extends StatelessWidget {
    const MyItems(this.icon, this.heading, this.color, this.routeName);
 ...

 IconButton(
                          icon: Icon(icon),
                          iconSize: 20,
                          color: Colors.white,
                          onPressed: () {
                            Navigator.pushNamed(context, routeName);
                          },
                        )

working demo

enter image description here

full code

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

List<StaggeredTile> _staggeredTiles = const <StaggeredTile>[
  StaggeredTile.extent(2, 150.0),
  StaggeredTile.extent(1, 150.0),
  StaggeredTile.extent(1, 150.0),
  StaggeredTile.extent(2, 150.0),
  StaggeredTile.extent(1, 150.0),
  StaggeredTile.extent(1, 150.0),
  StaggeredTile.extent(2, 150.0),
];

List<Widget> _tiles = const <Widget>[
  const MyItems(Icons.shop, "Text1 Here", 0xff42a5f5, "/first"),
  const _Example01Tile(Colors.green, Icons.widgets),
  const _Example01Tile(Colors.amber, Icons.panorama_wide_angle),
  const MyItems(Icons.shop, "Text 2 Here", 0xff42a5f5, "/second"),
  const _Example01Tile(Colors.deepOrange, Icons.send),
  const _Example01Tile(Colors.indigo, Icons.airline_seat_flat),
  const _Example01Tile(Colors.red, Icons.bluetooth),
  const _Example01Tile(Colors.pink, Icons.battery_alert),
  const _Example01Tile(Colors.purple, Icons.desktop_windows),
  const _Example01Tile(Colors.blue, Icons.radio),
];

class Example01 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Example 01'),
        ),
        body: Padding(
            padding: const EdgeInsets.only(top: 12.0),
            child: StaggeredGridView.count(
              crossAxisCount: 4,
              staggeredTiles: _staggeredTiles,
              children: _tiles,
              mainAxisSpacing: 4.0,
              crossAxisSpacing: 4.0,
              padding: const EdgeInsets.all(4.0),
            )));
  }
}

class _Example01Tile extends StatelessWidget {
  const _Example01Tile(this.backgroundColor, this.iconData);

  final Color backgroundColor;
  final IconData iconData;

  @override
  Widget build(BuildContext context) {
    return Card(
      color: backgroundColor,
      child: InkWell(
        onTap: () {},
        child: Center(
          child: Padding(
            padding: const EdgeInsets.all(4.0),
            child: Icon(
              iconData,
              color: Colors.white,
            ),
          ),
        ),
      ),
    );
  }
}

class MyItems extends StatelessWidget {
  const MyItems(this.icon, this.heading, this.color, this.routeName);

  final int color;
  final IconData icon;
  final String heading;
  final String routeName;

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.white,
      elevation: 12.0,
      shadowColor: Color(0xff2962ff),
      borderRadius: BorderRadius.circular(20.0),
      child: Center(
          child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        //Text here
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Text(
                            heading,
                            style: TextStyle(
                              color: new Color(color),
                              fontSize: 18.0,
                            ),
                          ),
                        ), //text

                        //icon
                        Material(
                          color: new Color(color),
                          borderRadius: BorderRadius.circular(24.0),
                          child: Padding(
                            padding: const EdgeInsets.all(16.0),
                            child: IconButton(
                              icon: Icon(icon),
                              iconSize: 20,
                              color: Colors.white,
                              onPressed: () {
                                Navigator.pushNamed(context, routeName);
                              },
                            ),
                          ),
                        ),
                      ],
                    ),
                  ]))),
    );
  }
}

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        // When navigating to the "/" route, build the FirstScreen widget.
        '/': (context) => Example01(),
        '/first': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
      },
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text("First Screen");
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text("Second Screen");
  }
}

Answered By – chunhunghan

Answer Checked By – Gilberto Lyons (FlutterFixes Admin)

Leave a Reply

Your email address will not be published.