flutter - 使用不包含 Navigator 的上下文请求的 Navigator 操作

我正在尝试在 onTap 中启动新屏幕,但出现以下错误:

Navigator operation requested with a context that does not include a Navigator.

我用来导航的代码是:

onTap: () { Navigator.of(context).pushNamed('/settings'); },

我在我的应用中设置了如下路线:

routes: <String, WidgetBuilder>{
    '/settings': (BuildContext context) => new SettingsPage(),
},

我尝试使用股票示例应用程序复制代码。我查看了 Navigator 和 Route 文档,但无法弄清楚如何使上下文包含 Navigator。 onTap 中使用的 context 是从传递给 build 方法的参数中引用的:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

SettingsPage 是一个类如下:

class SettingsPage extends Navigator {

Widget buildAppBar(BuildContext context) {
  return new AppBar(
    title: const Text('Settings')
  );
}

@override
Widget build(BuildContext context) {
  return new Scaffold(
    appBar: buildAppBar(context),
  );
 }
}

最佳答案

TLDR:将需要访问 Navigator 的小部件包装到 Builder 或将该子树提取到一个类中。并使用新的 BuildContext 来访问 Navigator


此错误与目的地无关。发生这种情况是因为您使用了一个不包含 Navigator 实例作为父级的 context

那我该如何创建一个 Navigator 实例呢?

这通常通过在小部件树中插入 MaterialAppWidgetsApp 来完成。虽然您可以直接使用 Navigator 手动完成,但不太推荐。然后,此类小部件的所有子级都可以使用 Navigator.of(context) 访问 NavigatorState

等等,我已经有一个 MaterialApp/WidgetsApp !

很可能是这种情况。但是,当您使用 MaterialApp/WidgetsApp 的父级 context 时,仍然会发生此错误。

这是因为当您执行 Navigator.of(context) 时,它将从与所使用的 context 关联的小部件开始。然后在小部件树中向上移动,直到找到 Navigator 或没有更多小部件。

在第一种情况下,一切都很好。第二,它抛出一个

Navigator operation requested with a context that does not include a Navigator.

那么,我该如何解决呢?

首先,让我们重现这个错误:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Center(
        child: RaisedButton(
          child: Text("Foo"),
          onPressed: () => Navigator.pushNamed(context, "/"),
        ),
      ),
    );
  }
}

此示例创建一个按钮,该按钮尝试在单击时转到“/”,但会引发异常。

请注意,在

  onPressed: () => Navigator.pushNamed(context, "/"),

我们使用 context 传递给 MyAppbuild

问题是,MyApp 实际上是MaterialApp 的父级。因为它是实例化 MaterialApp 的小部件!因此 MyAppBuildContext 没有 MaterialApp 作为父级!

要解决这个问题,我们需要使用不同的context

在这种情况下,最简单的解决方案是引入一个新的小部件作为 MaterialApp 的子级。然后使用该小部件的上下文执行 Navigator 调用。

有几种方法可以实现这一点。您可以将 home 提取到自定义类中:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHome()
    );
  }
}

class MyHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: RaisedButton(
          child: Text("Foo"),
          onPressed: () => Navigator.pushNamed(context, "/"),
        ),
      );
  }
}

或者你可以使用 Builder :

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) => Center(
              child: RaisedButton(
                child: Text("Foo"),
                onPressed: () => Navigator.pushNamed(context, "/"),
              ),
            ),
      ),
    );
  }
}

https://stackoverflow.com/questions/44004451/

相关文章:

android - 如何在 FlatButton 单击时关闭 AlertDialog?

dart - 在 Flutter 中显示 SnackBar

flutter - 遍历列表以在 Flutter 中呈现多个小部件?

java - Flutter.io Android 许可证状态未知

dart - 无法更改 TextField 边框颜色

dart - Flutter:如何解决错误导入包:http/http.dart

flutter - 如何更改 appBar 后退按钮颜色

android - 所有小部件的 flutter 填充?

dart - 如何在 Flutter 中旋转 15 度?

flutter - 如何将清除按钮添加到 TextField 小部件