Как связать элементы Flutter StaggeredGridView по отдельности?

Следуя руководству по StaggeredGridView, я успешно создал страницу для отображения шахматной сетки текста и значка. В учебнике не было рассказа о том, как связать каждый элемент сетки по отдельности. Мне известны onTap, GestureDetector, OnPressed, но я не могу понять, как реализовать что-либо из них в этом макете сетки, чтобы каждый элемент мог ссылаться на другой маршрут страницы материала (или _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),
    ],
),

), // материал

Для каждого 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,

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

Похоже, что нет никакой информации о том, как решить эту проблему. Единственное, что я смог найти от автора, было «Есть несколько способов справиться с этим»:

  1. Использовать свойство Keys виджета

    TagButton (onPressed: (k) => onPress (k)), void onPress (Key id) {print ('нажатый $ id'); }

2. Назначьте обратный вызов, который вызывает разные методы для каждой кнопки.

  1. Или вы можете передать параметр, как показано ниже, и использовать переключатель для определения значения параметра и вызова соответствующего метода.

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

Но после долгой борьбы я просто не могу этого понять. Можно ли хотя бы по отдельности связать каждую смещенную сетку с их собственной уникальной ссылкой (маршрут страницы, UrlLauncher и т. Д.?)


person Mark    schedule 08.02.2020    source источник
comment
После бесчисленных часов попыток найти ответ единственное, что приблизилось к отдельному связыванию сеток, - это добавить событие щелчка над каждым элементом сетки, но когда я это сделал, эти сетки исчезли. Думаю, решения нет   -  person Mark    schedule 09.02.2020


Ответы (1)


Вы можете скопировать и вставить полный код ниже
Вы можете передать имя маршрута как String

фрагмент кода

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");
  }
}
person chunhunghan    schedule 10.02.2020
comment
Спасибо за ответ. Думаю, нет простого способа просто добавить ссылку для каждой сетки отдельно в исходный код? Я до сих пор не понимаю, как я могу связать каждую отдельную плитку отдельно (т.е. с другим MaterialPageRoute, UrlLauncher ..), поскольку все плитки называются одинаково - 'const _Example01Tile' или, в моем случае, 'const MyItems '. Попытайтесь осознать это, как я могу добавить отдельную ссылку на каждый элемент сетки? - person Mark; 10.02.2020
comment
пожалуйста, посмотрите мой обновленный ответ. Вы можете передать имя маршрута как String - person chunhunghan; 11.02.2020
comment
Спасибо за обстоятельный ответ, я очень ценю это. Мне трудно понять конструкторы, и мне трудно понять, как это работает, и почему так много кода требуется для такой, казалось бы, простой задачи. - person Mark; 12.02.2020
comment
пожалуйста, отметьте это как ответ, если это вам поможет, спасибо. если это вам не помогло, вы можете уточнить свой вопрос еще раз. Благодарю. - person chunhunghan; 13.02.2020
comment
Хотя я до сих пор этого не понимаю и пытаюсь понять, но вижу, что это работает. Я проголосовал за принятый ответ, хотя код полностью отличается от моего исходного кода, но ваш работает. Поскольку я новичок, у меня здесь нет репутации, поэтому здесь не учитываются мои голоса, что очень странно. - person Mark; 19.02.2020
comment
Вы можете пометить ответ как принятый, щелкнув галочку рядом с ответом, чтобы переключить его с серого на заполненный. Вы можете увидеть meta.stackexchange.com/questions/5234/, большое спасибо. - person chunhunghan; 19.02.2020
comment
Поскольку вы являетесь OP (исходным сообщением), вы не можете щелкнуть отметку «за» под отметкой 15. Но вы можете щелкнуть отметку «V» под отметкой «против». - person chunhunghan; 19.02.2020