Flutter学习(四):Navigator,Route

Flutter应用中的页面跳转实现由Navigator,Route来实现.

Navigator
Navigator是一个路由管理的widget,它通过一个栈来管理一个路由widget集合。通常当前屏幕显示的页面就是栈顶的路由。Navigator提供了一系列方法来管理路由栈,在此我们只介绍其最常用的两个方法:

Future push(BuildContext context, Route route)
将给定的路由入栈(即打开新的页面),返回值是一个Future对象,用以接收新路由出栈(即关闭)时的返回数据。

bool pop(BuildContext context, [ result ])
将栈顶路由出栈,result为页面关闭时返回给上一个页面的数据。

Navigator 还有很多其它方法,如Navigator.replace、Navigator.popUntil等,详情请参考API文档或SDK源码注释.

实例方法
Navigator类中第一个参数为context的静态方法都对应一个Navigator的实例方法, 比如Navigator.push(BuildContext context, Route route)等价于Navigator.of(context).push(Route route) route) ,后面介绍的命名路由相关方法也是一样的。

我们在代码中测试一下使用

import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          child: new RandomWordsWidget(),
        ),
        bottomNavigationBar: new FlatButton(
            onPressed: () {
              Navigator.push(context, new MaterialPageRoute(builder: (context) {
                return new NewPage();
              }));
            },
            child: Text('跳转到新界面')),
      ),
    );
  }
}

class NewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'New Page',
      home: new Scaffold(
        appBar: new AppBar(
          title: Text('New Page:Title'),
        ),
        body: Text('New Page:Body'),
      ),
    );
  }
}

class RandomWordsWidget extends StatefulWidget {
  @override
  createState() => new RandomWordsStatus();
}

class RandomWordsStatus extends State<RandomWordsWidget> {
  @override
  Widget build(BuildContext context) {
    final wordPair = new WordPair.random();
    return new Text(wordPair.asPascalCase);
  }
}

我们在界面底部添加了一个导航栏,点击后将会跳转到一个新的界面.运行后,点击,发现没有效果,出现了一个异常:

I/flutter (28564): The following assertion was thrown while handling a gesture:
I/flutter (28564): Navigator operation requested with a context that does not include a Navigator.
I/flutter (28564): The context used to push or pop routes from the Navigator must be that of a widget that is a
I/flutter (28564): descendant of a Navigator widget.
I/flutter (28564): When the exception was thrown, this was the stack:
I/flutter (28564): #0      Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:1379:9)
I/flutter (28564): #1      Navigator.of (package:flutter/src/widgets/navigator.dart:1386:6)
I/flutter (28564): #2      Navigator.push (package:flutter/src/widgets/navigator.dart:1011:22)
I/flutter (28564): #3      MyApp.build.<anonymous closure> (package:flutter_demo/main.dart:20:25)
I/flutter (28564): #4      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:513:14)
I/flutter (28564): #5      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:568:30)
I/flutter (28564): #6      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:120:24)
I/flutter (28564): #7      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:242:9)
I/flutter (28564): #8      TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:175:7)
I/flutter (28564): #9      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:369:9)
I/flutter (28564): #10     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
I/flutter (28564): #11     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)

异常显示,我们使用了一个不包含Navigator的Context来请求Navigator操作,而Navigator进行push或者pop操作时使用的Context必须是Navigator Widget的子类.

从代码中查看,我们使用的Context来自于build方法中,是从StatelessWidget中传递过来的.
具体的分析过程参考博文:
Flutter | 深入理解BuildContext

看过上文后,我们要解决这个问题,必须使用MaterialApp中的context.
我们将首页的代码提取一下,将Scaffold 提取出来,然后使用MaterialApp中的context.
具体代码如下:

import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: FirstPage(),
    );
  }
}
class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Welcome to Flutter'),
      ),
      body: new Center(
        child: new RandomWordsWidget(),
      ),
      bottomNavigationBar: new FlatButton(
          onPressed: () {
            Navigator.push(context, new MaterialPageRoute(builder: (context) {
              return new NewPage();
            }));
          },
          child: Text('跳转到新界面')),
    );
  }
}


class NewPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'New Page',
      home: new Scaffold(
        appBar: new AppBar(
          title: Text('New Page:Title'),
        ),
        body: Text('New Page:Body'),
      ),
    );
  }
}

class RandomWordsWidget extends StatefulWidget {
  @override
  createState() => new RandomWordsStatus();
}

class RandomWordsStatus extends State<RandomWordsWidget> {
  @override
  Widget build(BuildContext context) {
    final wordPair = new WordPair.random();
    return new Text(wordPair.asPascalCase);
  }
}

运行测试后完美

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值