mobile - Flutter 无法更改路由,因为 PopupMenuButton 未定义名称上下文如何解决?

标签 mobile routes flutter navigator

我想单击项目菜单 (PopupMenuItem) 并使用 Navigator.push 转到另一条路线,但方法内未定义上下文。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {

  final List<Choice> choices = const <Choice>[
    const Choice(title: 'Settings', icon: Icons.settings),
    const Choice(title: 'Log out', icon: Icons.exit_to_app),
    ];



  @override
  Widget build(BuildContext context) {
    final title = 'MyTitle';

    return MaterialApp(
      title: title,
      home: Scaffold(
        appBar: AppBar(
          title: Text(title),
          actions: <Widget>[
                PopupMenuButton<Choice>(
                  onSelected: onItemMenuPress,
                  itemBuilder: (BuildContext context) {
                    return choices.map((Choice choice) {
                      return PopupMenuItem<Choice>(
                          value: choice,
                          child: Row(
                            children: <Widget>[
                              Icon(
                                choice.icon,
                              ),
                              Container(
                                width: 10.0,
                              ),
                              Text(
                                choice.title,
                              ),
                            ],
                          ));
                    }).toList();
                  },
                ),
              ],
        ),
        body: Text("Hello world")
      ),
    );

  }

    void onItemMenuPress(Choice choice) {   
      if (choice.title == 'Log out') {
        print("Logout");
        Navigator.push(context, MaterialPageRoute(builder: (context) => LogoutRoute()));
      } 
  }

}

class Choice {
  const Choice({this.title, this.icon});

  final String title;
  final IconData icon;
}

class LogoutRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Logout"),
      ),
      body: Center(
        child: Text("Screen"),
      ),
    );
  }
}

我尝试以这种方式在 onItemMenuPress 中传递上下文:

void onItemMenuPress(Choice choice, BuildContext context)

但是:

onSelected: onItemMenuPress(context)

不工作。

这种方法都不起作用:

onSelected: (Choice c) { Navigator.push(context, MaterialPageRoute(builder: (context) => LogoutRoute())); }

我正在关注本教程: https://medium.com/flutter-community/building-a-chat-app-with-flutter-and-firebase-from-scratch-9eaa7f41782e

他的代码片段(与我的类似)似乎对他有用: https://github.com/duytq94/flutter-chat-demo/blob/master/lib/main.dart

我引用第235行(onSelected)和第199-205行(实际的onItemMenuPress方法)

这怎么可能?我该如何缓解? 谢谢

最佳答案

这里有:

MyApp    <------ context
  --> MaterialApp
   (--> Navigator built within MaterialApp)
      --> Scaffold
        --> App Bar
          --> ...

因此,当您使用上下文查找导航器时,您正在使用不在导航器下的 MyApp 上下文。 因此,我们可以创建一个新的无状态或有状态 Widget 子类来包含您的脚手架,因为其中的构建函数将指向该级别,或者我们可以使用生成器并定义构建器回调(具有指向构建器的上下文)以返回Scaffold

我们创建了新子类的工作代码 - HomeScreen :

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final title = 'MyTitle';
    return MaterialApp(
      title: title,
      home: HomeScreen(title),
    );
  }
}

class HomeScreen extends StatelessWidget {
  final String title;

  HomeScreen(this.title);

  final List<Choice> choices = const <Choice>[
    const Choice(title: 'Settings', icon: Icons.settings),
    const Choice(title: 'Log out', icon: Icons.exit_to_app),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(title),
          actions: <Widget>[
            PopupMenuButton<Choice>(
              onSelected: (val) => onItemMenuPress(val, context),
              itemBuilder: (BuildContext context) {
                return choices.map((Choice choice) {
                  return PopupMenuItem<Choice>(
                      value: choice,
                      child: Row(
                        children: <Widget>[
                          Icon(
                            choice.icon,
                          ),
                          Container(
                            width: 10.0,
                          ),
                          Text(
                            choice.title,
                          ),
                        ],
                      ));
                }).toList();
              },
            ),
          ],
        ),
        body: Text("Hello world"));
  }

  void onItemMenuPress(Choice choice, BuildContext context) {
    if (choice.title == 'Log out') {
      print("Logout");
      Navigator.push(
          context, MaterialPageRoute(builder: (context) => LogoutRoute()));
    }
  }
}

class Choice {
  const Choice({this.title, this.icon});

  final String title;
  final IconData icon;
}

class LogoutRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Logout"),
      ),
      body: Center(
        child: Text("Screen"),
      ),
    );
  }
}

关于mobile - Flutter 无法更改路由,因为 PopupMenuButton 未定义名称上下文如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54811646/

相关文章:

javascript - 按钮宽度调整为窗口宽度(或包含 div)

android - 检查unity3D(iOS,Android)中是否有SMS

asp.net-mvc-3 - MVC 3 子域路由

java - JGraphT库如何访问边的顶点

Flutter Run 不起作用,在 iPhone 上启动应用程序时出错

blackberry - 随着 BBX 的出现,为旧操作系统编写黑莓应用程序是否值得?

jQuery函数在移动设备的新窗口中打开链接

algorithm - 基于两个指标(距离、成本)的图形中的最佳(折衷)路径

flutter - 循环进度指示器 - 数学问题

windows - 无法在 MS VS 代码上运行 flutter 命令