Flutter 使用不包含导航器的上下文请求的导航器操作
我试图在onTap中启动新屏幕,但出现以下错误: 请求的导航器操作的上下文不包括 领航员 我用来导航的代码是:Flutter 使用不包含导航器的上下文请求的导航器操作,flutter,Flutter,我试图在onTap中启动新屏幕,但出现以下错误: 请求的导航器操作的上下文不包括 领航员 我用来导航的代码是: onTap: () { Navigator.of(context).pushNamed('/settings'); }, 我已在我的应用程序中设置了一条路线,如下所示: routes: <String, WidgetBuilder>{ '/settings': (BuildContext context) => new SettingsPage(), },
onTap: () { Navigator.of(context).pushNamed('/settings'); },
我已在我的应用程序中设置了一条路线,如下所示:
routes: <String, WidgetBuilder>{
'/settings': (BuildContext context) => new 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),
);
}
}
SettingsPage是一个类,如下所示:
routes: <String, WidgetBuilder>{
'/settings': (BuildContext context) => new 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),
);
}
}
我在颤振应用程序中设置了一个简单的路由示例:
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
home: new MyHomePage(),
routes: <String, WidgetBuilder>{
'/settings': (BuildContext context) => new SettingsPage(),
},
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('TestProject'),
),
body: new Center(
child: new FlatButton(
child: const Text('Go to Settings'),
onPressed: () => Navigator.of(context).pushNamed('/settings')
)
)
);
}
}
class SettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('SettingsPage'),
),
body: new Center(
child: new Text('Settings')
)
);
}
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(新的MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回新材料PP(
标题:“颤振演示”,
主页:新建MyHomePage(),
路线:{
“/settings”:(BuildContext上下文)=>new SettingsPage(),
},
);
}
}
类MyHomePage扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
归还新脚手架(
appBar:新的appBar(
标题:新文本(“TestProject”),
),
正文:新中心(
孩子:新的扁平按钮(
子项:常量文本(“转到设置”),
onPressed:()=>Navigator.of(context.pushName)(“/settings”)
)
)
);
}
}
类设置SPAGE扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
归还新脚手架(
appBar:新的appBar(
标题:新文本(“设置页面”),
),
正文:新中心(
子项:新文本(“设置”)
)
);
}
}
注意,SettingsPage扩展了无状态小部件,而不是导航器。我无法重现你的错误
此示例是否有助于您构建应用程序?请告诉我是否可以帮助您。TLDR:将需要访问Navigator
的小部件包装到Builder
中,或将该子树提取到类中。并使用新的BuildContext
访问Navigator
此错误与目标无关。发生这种情况的原因是您使用了一个不包含
导航器的上下文
作为父实例
那么如何创建导航器实例呢?
这通常是通过在小部件树中插入MaterialApp
或WidgetApp
来实现的。虽然您可以直接使用Navigator
手动执行,但不推荐这样做。然后,此类小部件的所有子部件都可以使用Navigator.of(context)
访问Navigator.state
等等,我已经有了MaterialApp
/WidgetApp
强>
很可能是这样。但是,当您使用上下文时,仍然可能发生此错误,该上下文是MaterialApp
/WidgetApp
的父级
这是因为当您执行(上下文)
的Navigator.of时,它将从与所使用的上下文相关联的小部件开始。然后在小部件树中向上移动,直到找到一个导航器
,或者不再有小部件
在第一种情况下,一切都很好。在第二种情况下,它抛出一个
使用不包含导航器的上下文请求的导航器操作
那么,如何修复它呢?
首先,让我们重现这个错误:
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, "/"),
我们使用传递给MyApp
的build
的context
问题是,MyApp
实际上是MaterialApp
的父级。因为是小部件实例化了MaterialApp
!因此MyApp
的BuildContext
没有MaterialApp
作为父级
为了解决这个问题,我们需要使用不同的上下文
在这种情况下,最简单的解决方案是引入一个新的小部件作为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, "/"),
),
),
),
);
}
}
完整且经过测试的解决方案:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:my-app/view/main-view.dart';
class SplashView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Builder(
builder: (context) => new _SplashContent(),
),
routes: <String, WidgetBuilder>{
'/main': (BuildContext context) => new MainView()}
);
}
}
class _SplashContent extends StatefulWidget{
@override
_SplashContentState createState() => new _SplashContentState();
}
class _SplashContentState extends State<_SplashContent>
with SingleTickerProviderStateMixin {
var _iconAnimationController;
var _iconAnimation;
startTimeout() async {
var duration = const Duration(seconds: 3);
return new Timer(duration, handleTimeout);
}
void handleTimeout() {
Navigator.pushReplacementNamed(context, "/main");
}
@override
void initState() {
super.initState();
_iconAnimationController = new AnimationController(
vsync: this, duration: new Duration(milliseconds: 2000));
_iconAnimation = new CurvedAnimation(
parent: _iconAnimationController, curve: Curves.easeIn);
_iconAnimation.addListener(() => this.setState(() {}));
_iconAnimationController.forward();
startTimeout();
}
@override
Widget build(BuildContext context) {
return new Center(
child: new Image(
image: new AssetImage("images/logo.png"),
width: _iconAnimation.value * 100,
height: _iconAnimation.value * 100,
)
);
}
}
导入'dart:async';
进口“包装:颤振/材料.省道”;
导入“package:my app/view/main view.dart”;
类SplashView扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回新材料PP(
住家:建筑商(
生成器:(上下文)=>新建内容(),
),
路线:{
“/main”:(BuildContext上下文)=>new MainView()}
);
}
}
类\u SplashContent扩展StatefulWidget{
@凌驾
_SplashContentState createState()=>new_SplashContentState();
}
类_SplashContentState扩展了状态
使用SingleTickerProviderStateMixin{
var_Iconanimation控制器;
var_iconAnimation;
startTimeout()异步{
变量持续时间=常数持续时间(秒:3);
返回新计时器(持续时间、handleTimeout);
}
void handleTimeout(){
Navigator.pushReplacementNamed(context,“/main”);
}
@凌驾
void initState(){
super.initState();
_iconAnimationController=新的AnimationController(
vsync:this,duration:newduration(毫秒:2000));
_iconAnimation=新曲线动画(
父对象:_iconAnimationController,曲线:Curves.easeIn);
_iconAnimation.addListener(()=>this.setState((){}));
_iconAnimationController.forward();
startTimeout();
}
@凌驾
小部件构建(构建上下文){
返回新中心(
孩子:新形象(
图像:新资产图像(“images/logo.png”),
宽度:_iconAnimation.value*100,
高度:_iconAnimation.value*100,
)
);
}
}
Hy伙计们,我也有同样的问题。这对我来说是不可能的。我找到的解决办法很简单。我所做的只是一个简单的代码:
void main() {
runApp(MaterialApp(
home: YOURAPP() ,
),
);
}
我希望是有用的。M
void main() => runApp(MaterialApp(
title: "App",
home: HomeScreen(),
));
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Title'),
),
body: Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: RaisedButton(
onPressed: () {
//right way: use context in below level tree with MaterialApp
Navigator.push(context,
MaterialPageRoute(builder: (context) => ScanScreen()));
},
child: const Text('SCAN')),
)),
);
}
}
final _navKey = GlobalKey<NavigatorState>();
void _navigateToLogin() {
_navKey.currentState.popUntil((r) => r.isFirst);
_navKey.currentState.pushReplacementNamed(LoginRoute.name);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: _navKey,
...
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text("Title"),
),
body: new Center(child: new Text("Click Me")),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add),
backgroundColor: Colors.orange,
onPressed: () {
print("Clicked");
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new AddTaskScreen()),
);
},
),
),
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomeScreen());
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Title"),
),
body: new Center(child: new Text("Click Me")),
floatingActionButton: new FloatingActionButton(
child: new Icon(Icons.add),
backgroundColor: Colors.orange,
onPressed: () {
print("Clicked");
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new AddTaskScreen()),
);
},
),
);
}
}
builder: (context) => Center(
child: RaisedButton(
child: Text("Foo"),
onPressed: () => Navigator.pushNamed(context, "/"),
),
void main() => runApp(MyApp());
void main() {
runApp(MaterialApp(
title: 'Your title',
home: MyApp(),));}
MaterialApp(
navigatorKey: Get.key,
initialRoute: "/",
);
`void main() {
runApp(MaterialApp(
title: 'Your title',
home: MyApp(),));}`