【问题标题】:How to add navigation route to Card in Flutter如何在 Flutter 中向 Card 中添加导航路线
【发布时间】:2020-02-26 13:04:07
【问题描述】:

在下面的代码中,我在卡片上有一个方法 myMenu。点击卡片时如何导航到另一个页面?将有几个这样的卡片将链接到它自己的页面内容。每次我添加一个函数时,它都会给出一个错误。我该如何正确操作?

import 'package:flutter/material.dart';
import 'package:tarjous_app/gridview_demo.dart';

void main(List<String> args) {
  runApp(
      new MaterialApp(home: TarjousAle(), debugShowCheckedModeBanner: false));
}

class TarjousAle extends StatefulWidget {
  @override
  _TarjousAleState createState() => _TarjousAleState();
}

class _TarjousAleState extends State<TarjousAle> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
        title: Text("Study Plan"),
        backgroundColor: Colors.amber,
      ),
      body: Container(
        child: GridView.count(
          crossAxisCount: 3,
          children: <Widget>[
            MyMenu(
              title: "Records",
              icon: Icons.account_balance_wallet,
              shape: Colors.brown,
            ),
            MyMenu(
              title: "Academy",
              icon: Icons.account_balance,
              shape: Colors.grey,
            ),
          ],
        ),
      ),
    );
  }
}

class MyMenu extends StatelessWidget {
  MyMenu({this.title, this.icon, this.shape});

  final String title;
  final IconData icon;
  final MaterialColor shape;

  @override
  Widget build(BuildContext context) {
    return Card(
      margin: EdgeInsets.all(9.0),
      child: InkWell(           
      onTap: () => Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => GridViewDemo()),
      ),
        splashColor: Colors.amberAccent,
        child: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Icon(
                icon,
                size: 80.0,
                color: shape,
              ),
              Text(title, style: new TextStyle(fontSize: 18.0))
            ],
          ),
        ),
      ),
    );
  }
}

在墨水池小部件中,我添加了一个适用于所有卡片的功能。但我真的希望每张卡片都能导航到自己的页面。例如,记录应该导航到它自己的记录页面,对于学院到学院页面也是如此

【问题讨论】:

  • "How do I navigate to another page when the card is tapped?" - 请参阅 NavigatorNavigatorState 类文档 - Navigation & routing 也会有所帮助
  • 我明白你的解释,但我真正需要的是让每张卡片导航到自己的页面。谢谢

标签: flutter


【解决方案1】:

用 InkWell 小部件包装卡片并在 onTap 方法中定义您的 navigator.push。

    class CardWidget extends StatelessWidget {
      final Function onTapCard;

      const CardWidget({Key key, @required this.onTapCard}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return Card(
          margin: EdgeInsets.all(9.0),
          child: InkWell(
            onTap: onTapCard,
            splashColor: Colors.amberAccent,
            child: Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Icon(
                    icon,
                    size: 80.0,
                    color: shape,
                  ),
                  Text(title, style: new TextStyle(fontSize: 18.0))
                ],
              ),
            ),
          ),
        );
      }

}

那么我们这里有我们的清单

class CardList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        CardWidget(
          onTapCard: () => Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => YourSecondPage()),
          ),
        ),
        CardWidget(
          onTapCard: Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => YourThirdPage()),
          ),
        ),
      ],
    );
  }
}

【讨论】:

  • 在已编辑的墨水池小部件中,每张卡片都导航到“GridViewDemo()”页面。但我希望他们每个人都导航到自己的页面。有没有办法给每张卡片添加一个功能(MyMenu(title: "Academy", icon: Icons.account_balance, shape: Colors.grey,) 我对flutter还是很陌生,请见谅
  • 如果您有无限数量的卡片,您可以创建一个 Listview.builder,您只需返回卡片即可。但如果您有一定数量的卡片,您可以使用卡片小部件创建列表视图、行或列。在另一个类中分离卡片,然后将 onTap 作为函数传递
【解决方案2】:

GestureDetector包裹卡片,你可以使用opnTap属性。 更多详情Official Documentation

【讨论】:

    【解决方案3】:

    请注意,要导航到某个页面,您的上下文必须包含父级的 Navigator 实例。因此,如果您尝试直接从 MaterialApp 导航,您可能会遇到问题。我不会在此赘述这一点,因为在 thread 中已经很好地解释了这一点,但如果您碰巧遇到它,请记住这一点。

    已编辑以解决 cmets:

    我会为你的情况做这样的事情。命名路线可让您轻松指定您希望卡片将您带到哪条路线,如果您希望同一个小部件将您带到不同的路线,您需要这样做。

    import 'package:flutter/material.dart';
    
    void main(List<String> args) {
      runApp(
        new MaterialApp(
          home: TarjousAle(),
          debugShowCheckedModeBanner: false,
          routes: {
            GridViewDemo.route: (context) => GridViewDemo(),
            AnotherDemo.route: (context) => AnotherDemo(),
          },
        ),
      );
    }
    
    class TarjousAle extends StatefulWidget {
      @override
      _TarjousAleState createState() => _TarjousAleState();
    }
    
    class _TarjousAleState extends State<TarjousAle> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: new AppBar(
            title: Text("Study Plan"),
            backgroundColor: Colors.amber,
          ),
          body: Container(
            child: GridView.count(
              crossAxisCount: 3,
              children: <Widget>[
                MyMenu(
                  title: "Records",
                  icon: Icons.account_balance_wallet,
                  shape: Colors.brown,
                  route: GridViewDemo.route
                ),
                MyMenu(
                  title: "Academy",
                  icon: Icons.account_balance,
                  shape: Colors.grey,
                  route: AnotherDemo.route
                ),
              ],
            ),
          ),
        );
      }
    }
    
    class MyMenu extends StatelessWidget {
      MyMenu({this.title, this.icon, this.shape, this.route});
    
      final String title;
      final IconData icon;
      final MaterialColor shape;
      final String route;
    
      @override
      Widget build(BuildContext context) {
        return Card(
          margin: EdgeInsets.all(9.0),
          child: InkWell(
            onTap: () => Navigator.pushNamed(context, route),
            splashColor: Colors.amberAccent,
            child: Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Icon(
                    icon,
                    size: 80.0,
                    color: shape,
                  ),
                  Text(title, style: new TextStyle(fontSize: 18.0))
                ],
              ),
            ),
          ),
        );
      }
    }
    
    class GridViewDemo extends StatelessWidget {
      static String route = '/demo';
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.brown,
          appBar: AppBar(title: Text('Grid view demo')),
          body: Center(
            child: Text('Grid view demo'),
          ),
        );
      }
    }
    
    class AnotherDemo extends StatelessWidget {
      static String route = '/another';
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.grey,
          appBar: AppBar(title: Text('Another demo')),
          body: Center(
            child: Text('Another demo'),
          ),
        );
      }
    }
    

    您可以在official docsanother docs page 中阅读有关导航基础知识的更多信息,如果您喜欢命名的路线。

    【讨论】:

    • 请检查上面的编辑代码和我的cmets。谢谢
    • 我已经更新了代码以解决您概述的情况 - 我希望它更清楚一点。
    • 是的,谢谢它的工作。但我不明白为什么我必须在 GridViewDemo 类中声明路由才能工作。请解释一下。
    • 如果你在谈论一个字符串 (/demo),那是没有必要的 - 你可以在你方便的地方定义路由(例如,一个单独的文件,或者只是硬编码字符串需要)。我这样做是为了让与特定小部件相关的所有内容都放在一个地方。但是,这绝对不是硬性要求。很抱歉,如果这造成任何混乱!
    • 不,很好,先生。我只是想知道它是否需要。谢谢。
    【解决方案4】:

    尝试将您的 Card 包装在 GestureDetector 中,如下所示:

    GestureDetector (
    child: Card(),
    onTap: () {},
    ),
    

    【讨论】:

      【解决方案5】:

      您可以在构造函数中接收页面,然后转到该页面,如下所示:

      class MyMenu extends StatelessWidget {
        MyMenu({this.title, this.icon, this.shape, this.page});
      
        final Widget page;
        ...
      }
      

      然后,在onTap

      onTap: () => Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => page),
      )
      

      所以现在你可以这样做了:

      MyMenu(
        ...
        page: GridViewDemo1(),
      ),
      MyMenu(
        ...
        page: GridViewDemo2(),
      )
      

      【讨论】:

      • 我也试过你的代码,但是 widget.page 在 onTap 方法中给出了一个错误
      • 它说“没有为类 'Widget' 定义 getter 'page'。尝试导入定义 'page' 的库,将名称更正为现有 getter 的名称,或定义一个名为 'page'.dart(undefined_getter) " 的 getter 或字段
      • 因为当 widget.page 是小写字母时,它会给出:未定义的名称“widget”。尝试将名称更正为已定义的名称,或定义 name.dart(undefined_identifier) 但是当我将其更改为大写字母(Widget.page)时,它会给出另一个错误
      • 我没有意识到你使用的是StatelessWidget而不是StatefulWidget,所以你应该直接使用'page'而不是'widget.page'
      • 很好,现在可以了。谢谢。我真的已经从你们那里学到了很多。我很感激
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      • 2022-07-05
      • 1970-01-01
      • 2020-08-16
      相关资源
      最近更新 更多