我正在尝试在 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 实例呢?
这通常通过在小部件树中插入 MaterialApp
或 WidgetsApp
来完成。虽然您可以直接使用 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
传递给 MyApp
的 build
。
问题是,MyApp
实际上是MaterialApp
的父级。因为它是实例化 MaterialApp
的小部件!因此 MyApp
的 BuildContext
没有 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, "/"),
),
),
),
);
}
}
关于flutter - 使用不包含 Navigator 的上下文请求的 Navigator 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44004451/