如何 link 单独 Flutter StaggeredGridView 项目?

How to link Flutter StaggeredGridView items individually?

按照 StaggeredGridView 上的教程,我成功构建了一个页面来显示文本和图标的交错网格。本教程没有解释如何分别 link 每个网格项目。我知道 onTap、GestureDetector、OnPressed,但我不知道如何在此网格布局中实现其中任何一个,以便每个元素都可以 link 到不同的 material 页面路由(或 _UrlLauncher,等等)

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

我们为每个 "MyItems" 创建了一个方法和参数:

  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 are couple of ways to tackle it":

  1. 使用小部件的键属性

    TagButton(onPressed: (k) => onPress(k)), void onPress(Key id) { 打印('pressed $id'); }

2.Assign 为每个按钮调用不同方法的回调

  1. 或者你也可以像下面这样传一个参数,然后用switch来识别参数值,调用相应的方法。

    onPressed: () => onButtonPressed('okButton'),

但经过一番努力,我就是无法理解这一点。甚至可以单独 link 每个交错网格到它们自己独特的 link (页面路由、UrlLauncher 等?

您可以复制粘贴 运行 下面的完整代码
您可以将路由名称作为字符串

传递

代码片段

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);
                          },
                        )

工作演示

完整代码

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");
  }
}