今天咱們來說講利用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如何跳轉,下一篇再見吧