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

时间:2019-02-21 16:16:21

标签: 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方法)

怎么可能?我该如何保存? 谢谢

2 个答案:

答案 0 :(得分:1)

您在这里:

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

因此,当您使用上下文查找导航器时,将使用MyApp的上下文,该上下文不在导航器下。 因此我们可以创建一个新的Stateless或Stateful Widget子类来包含您的Scaffold,因为其中的构建函数将指向该级别,或者我们可以使用Builder并定义构建器回调(其中有一个指向构建器的上下文)以返回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"),
      ),
    );
  }
}

答案 1 :(得分:0)

发生这种情况是因为您的Flutter SDK和Dark SDK无法正常工作。您可以解决此问题,从而升级您的Flutter SDK。进入终端并输入

颤振升级--force

在升级完后,您的fld sdk和dark sdk将被升级,安装完成后,您会没事的。