今天咱们来说讲利用Navigator来跳转页面的功能,承接上一篇flutter之从零开始搭建(一)之 BottomNavigationBar继续讲。git
页面跳转是咱们在入门学习的必备知识,在flutter中,路由跳转是由Navigator来操做的。github
Navigator的跳转有两种,一种是显示跳转,须要咱们在MaterialPageRoute中指定widgetbash
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
//指定跳转的页面
return new Demo1();
},));
复制代码
另外一种是隐身跳转,这种跳转须要先定义,后使用,跳转方式就像Arouter同样的路径方式,定义部分须要在MaterialApp下定义routes,routes就跟一个Map<path,Page>
集合同样,定义好了path对应的page,那么下次跳转,咱们就能够针对path去跳转了less
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
body: new Center(child: new RaisedButton(onPressed: _pushPage,child: new Text("跳转"))),
),
//定义路由
routes: <String,WidgetBuilder>{
"/demo1":(BuildContext context)=>new Demo1(),
},
);
复制代码
跳转使用ide
Navigator.of(context).pushNamed("/demo1");
复制代码
知道路由如何跳转了,那么,咱们开始实战吧布局
咱们看到,路由的跳转都带着一个context参数,这其中有无数的坑须要本身去理解,接下来我会展现出来。post
仍是承接上一篇博文flutter之从零开始搭建(一)之 BottomNavigationBar,咱们先看下MyPage页面,先给出以下代码学习
import 'package:flutter/material.dart';
import 'package:codelang/widget/Demo1.dart';
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: new PageWidget(),
routes: <String,WidgetBuilder>{
"/demo1":(BuildContext context)=>new Demo1(),
},
);
}
}
class PageWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new PageState();
}
}
class PageState extends State<PageWidget> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(child: new RaisedButton(onPressed: _pushPage,child: new Text("跳转"),),),
);
}
_pushPage(){
// Navigator.of(context).pushNamed("/demo1");
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new Demo1();
},));
}
}
复制代码
你们总体看一下代码,其实没什么错误的地方,看起来一切都很正常,而后咱们来看下效果图ui
what fuck!!! 跳转的页面怎么没有覆盖全屏,因此,这种方式确定是不可取的。this
咱们先停下来想一想,咱们当前页面PageState
是在PageWidget
布局上面,PageWidget还有一个上层布局叫MyPage
,咱们是否是能够理解为,Navigator.of(context)
的这个context
指向的是上层MyPage
布局的context
,致使了页面路由跳转是在MyPage
页面进行。
那么有什么解决办法呢?既然是context缘由,那么,咱们必须得拿到MyPage
的上一层context
,咱们再想一想,MyPage
至关于一个fragment
,是由MainPage
页面组成的,咱们只须要拿将MainPage
页面的context传递给MyPage
不就好了吗?接下来开干试试。
打开
MainPage
给MyPage的构造方法传递MainPage
的context
_bodys = [
new HomePage(),
new ShopPage(),
new MsgPage(),
new MyPage(context)
];
复制代码
打开
MyPage
MyPage拿到MainPage
的parentContext,而后将parentContext传递给PageWidget
,PageState
能够经过widget.X
的形式,能够拿到PageWidget
的变量
import 'package:flutter/material.dart';
import 'package:codelang/widget/Demo1.dart';
class MyPage extends StatelessWidget {
var parentContext;
MyPage(this.parentContext);
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: new PageWidget(parentContext),
routes: <String,WidgetBuilder>{
"/demo1":(BuildContext context)=>new Demo1(),
},
);
}
}
class PageWidget extends StatefulWidget {
var parentContext;
PageWidget(this.parentContext);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new PageState();
}
}
class PageState extends State<PageWidget> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(child: new RaisedButton(onPressed: _pushPage,child: new Text("跳转"),),),
);
}
_pushPage(){
// Navigator.of(widget.parentContext).pushNamed("/demo1");
Navigator.of(widget.parentContext).push(new MaterialPageRoute(builder: (context) {
return new Demo1();
},));
}
}
复制代码
看下效果图
嗯,很完美的解决,你们有没有看到我_pushPage
方法中注释了的pushNamed
方式的跳转,你们猜猜,用这种方式会不会出错?5秒钟的思考哦.
OK,来揭晓答案,确定是不行的,咱们知道,routes的定义是在MyPage
中的,而咱们饿路由跳转拿到的parentContext
是MainPage
的,因此,会报找不到这个路由的错误,如何解决呢?我相信到这你们应该都清楚了,那就是在MainPage
中去定义这个routes,具体能够看以下
class MainPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
routes: <String, WidgetBuilder>{
"/demo1": (BuildContext context) => new Demo1(),
},
home: new MainPageWidget());
}
}
复制代码
这样跳转就能够了,效果图我就不贴出来了,跟上面同样。
你觉得就这样结束了?哈哈,早着呢,在写这篇博文的时候,我又发现了一个好玩的地方,为了区分,我在HomePage
页面去写这个例子,代码很少,你们看看
HomePage
import 'package:flutter/material.dart';
import 'package:codelang/widget/Demo1.dart';
class HomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return new HomeState();
}
}
class HomeState extends State<HomePage> {
@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
body: new Center(child: new RaisedButton(onPressed: _pushPage,child: new Text("跳转"))),
),
);
}
_pushPage() {
// Navigator.of(context).pushNamed("/demo1");
Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
return new Demo1();
},));
}
}
复制代码
在这个路由跳转中,我用了context来跳转,你们再猜猜,这种方式能够嘛?5秒钟的思考时间
答案揭晓,是能够的哦,为何这样又能够了呢?
HomePage
与MyPage
的区别在于定义这个widget时,MyPage
最外套的一层是StatelessWidget
,而HomePage
最外套的一层是StatefulWidget
,StatelessWidget
是一个无状态的widget,难道是他阻隔了context的传递?具体的我也不清楚,只能去猜。
你们再猜猜仍是那段注释了的pushNamed
的代码,可不能够跳转呢?哈哈,固然是能够的,由于咱们在前面的时候,就已经在mainPage
中定义了routes
好了,路由这篇说完了,惟一坑就是context的问题,看了这一篇,相信不少人都理解了Navigator如何跳转,下一篇再见吧