flutter之從零開始搭建(二)之 Navigator路由

今天咱們來說講利用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

image

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傳遞給PageWidgetPageState能夠經過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();
    },));
  }
}
複製代碼

看下效果圖

image

嗯,很完美的解決,你們有沒有看到我_pushPage方法中註釋了的pushNamed方式的跳轉,你們猜猜,用這種方式會不會出錯?5秒鐘的思考哦.

  • 倒計時5s
  • 倒計時4s
  • 倒計時3s
  • 倒計時2s
  • 倒計時1s

OK,來揭曉答案,確定是不行的,咱們知道,routes的定義是在MyPage中的,而咱們餓路由跳轉拿到的parentContextMainPage的,因此,會報找不到這個路由的錯誤,如何解決呢?我相信到這你們應該都清楚了,那就是在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秒鐘的思考時間

  • 倒計時5s
  • 倒計時4s
  • 倒計時3s
  • 倒計時2s
  • 倒計時1s

答案揭曉,是能夠的哦,爲何這樣又能夠了呢?

HomePageMyPage的區別在於定義這個widget時,MyPage最外套的一層是StatelessWidget,而HomePage最外套的一層是StatefulWidgetStatelessWidget是一個無狀態的widget,難道是他阻隔了context的傳遞?具體的我也不清楚,只能去猜。

你們再猜猜仍是那段註釋了的pushNamed的代碼,可不能夠跳轉呢?哈哈,固然是能夠的,由於咱們在前面的時候,就已經在mainPage中定義了routes


好了,路由這篇說完了,惟一坑就是context的問題,看了這一篇,相信不少人都理解了Navigator如何跳轉,下一篇再見吧

gayhub連接

相關文章
相關標籤/搜索