简体   繁体   English

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

[英]Flutter can't change route because undefined name context with PopupMenuButton how to solve?

I want to click an item menu (PopupMenuItem) and go to another route using Navigator.push but context is undefined inside the method.我想单击一个项目菜单 (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"),
      ),
    );
  }
}

I have tried to pass a context in onItemMenuPress in this way:我试图以这种方式在 onItemMenuPress 中传递上下文:

void onItemMenuPress(Choice choice, BuildContext context)

but:但:

onSelected: onItemMenuPress(context)

is not working.不管用。

Neither this approach works:这种方法都不起作用:

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

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

and there is a snippet of his code (similar to mine) that seems to work for him: https://github.com/duytq94/flutter-chat-demo/blob/master/lib/main.dart并且有一段他的代码(类似于我的)似乎对他有用: https : //github.com/duytq94/flutter-chat-demo/blob/master/lib/main.dart

I refer to line 235 (onSelected) and lines 199-205 (actual onItemMenuPress method)我指的是第 235 行(onSelected)和第 199-205 行(实际的 onItemMenuPress 方法)

How is it possible?这怎么可能? How can I salve?我该如何解救? Thanks谢谢

Here you have :在这里你有:

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

So when you're using the context to find the Navigator, you're using a context for the MyApp which isn't under the navigator.因此,当您使用上下文来查找导航器时,您正在使用不在导航器下的 MyApp 的上下文。 so we can either make a new Stateless or Stateful Widget subclass to contain your Scaffold , as the build function within those will point at that level instead, or we can use a Builder and define the builder callback (which has a context pointing at the Builder) to return the Scaffold .所以我们可以创建一个新的 Stateless 或 Stateful Widget 子类来包含您的Scaffold ,因为它们中的构建函数将指向该级别,或者我们可以使用Builder并定义构建器回调(它有一个指向 Builder 的上下文) 返回Scaffold

Working Code we created new subclass - HomeScreen :我们创建了新子类的工作代码 - 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"),
      ),
    );
  }
}

It happens because your flutter SDK and dark SDK is not working properly.发生这种情况是因为您的 flutter SDK 和 dark SDK 无法正常工作。 you can solve this issues upgrading your flutter sdk.你可以通过升级你的 flutter sdk 来解决这个问题。 go to the terminal and type转到终端并输入

flutter upgrade --force颤振升级--force

after that your fluter sdk and dark sdk will be upgrade, after the installation complete you will be fine.之后你的fluter sdk和dark sdk将升级,安装完成后你会没事的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM