简介

大多数应用程序具有多个页面或视图,并且希望将用户从页面平滑过渡到另一个页面。Flutter的路由和导航功能可帮助管理应用中屏幕之间的命名和过渡。

管理多个页面时有两个核心概念和类:RouteNavigator。 一个 route 是一个屏幕或页面的抽象,Navigator 是管理 routeWidgetNavigator 可以通过 route 入栈和出栈来实现页面之间的跳转。

Navigator 导航

遇到的坑

在测试的时候,遇到过一个问题,问题就是在于 void main() => runApp(new IndexPage()) 。就是不能用这种写法。

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

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

class IndexPage extends StatelessWidget {

  @override
  Widget build(BuildContext context){

    return new MaterialApp(
      title: "测试",
      home: new Scaffold(
        appBar: new AppBar(title: new Text('第一个界面'),),
        body: new Center(
          child: new RaisedButton(onPressed: (){
            print(context);   // IndexPage
            Navigator.push(context, new MaterialPageRoute(builder: (context) => new ItemPage() ));
          }, child: new Text('跳转'),),
        ),
      ),
    );
  }
}

这里后来看了下官网,MaterialApp的主页成为导航器堆栈底部的路径。然后自己理解是:导航需要有一个根部的堆栈,然后 new MaterialApp(home: new MyAppHome()) 这里的 home 就充当了根部。
通过 void main() => runApp(new IndexPage()) 就是相对于是一个应用跳转到另外一个应用。

void main() {
  runApp(new MaterialApp(home: new MyAppHome()));
}

使用 Navigator.push 就是表示跳转到新的界面, 使用 Navigator.pop 就是返回上一个界面。逻辑其实就是将 一个界面加入到 Navigator 的堆栈中(push操作),然后将这个页面移出 Navigator 的堆栈(pop操作)。

在使用 Navigator.pushNavigator.pop 的时候,需要传入一个参数 context, 这个参数值表示当前的界面 。

完整代码实例

import 'package:flutter/material.dart';

/// 跳转到新页面并返回
void main() {
  runApp(new MaterialApp(
    title: "测试",                  //application名字
    home: new IndexPage(),          //初始化页面
  ));
}

/// 第一个页面
class IndexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar( title: new Text("第一个页面") ),
      body: new Center(
        child: new RaisedButton(
            child: new Text("点击跳转"),
            onPressed: () {
              print(context);  // 打印值:IndexPage
              //跳转到新的 页面我们需要调用 navigator.push方法 
              Navigator.push(
                  context,
                  new MaterialPageRoute( builder: (context) => new ItemPage()) );
            }),
      ),
    );
  }
}

/// 第二个页面
class ItemPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar( title: new Text("第二个页面") ),
      body: new Center(
        //onPressed  点击事件
        child: new RaisedButton(
            child: new Text("点我回第一个页面"),
            onPressed: () {
              //回到上一个页面 相当于finsh
              Navigator.pop(context);
            }
        ),
      ),
    );
  }
}

使用下面这种方式也是可以实现

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      // home 的值必须为 new PageName(), 这样子才能让 home 成为导航器堆栈底部的路径
      home: new IndexPage(title: '应用程序首页'),
    );
  }
}

跳转的方法可以独立出来,下面的写法也是可以的,使用 Navigator.of(context).push

class IndexPage extends StatelessWidget {

  @override
  Widget build(BuildContext context){

    // 点击跳转的方法
    _onPressed(){
      // Navigator.push(context, new MaterialPageRoute(builder: (context) => new ItemPage() ));
      Navigator.of(context).push(new MaterialPageRoute(builder: (context) => new ItemPage() ));
    }

    return new Scaffold(
        appBar: new AppBar(title: new Text('第一个界面'),),
        body: new Center(

          // 将点击的方法单独出去
          child: new RaisedButton(onPressed:_onPressed, child: new Text('跳转'),),
        ),
      );
  }
}

使用命名的路由导航

简单的理解就是说,将对应的路由定义在一个路由表中 Map<String, WidgetBuilder>,类似于'/a/b/c'

void main() {
  runApp(new MaterialApp(
    home: new MyAppHome(), // becomes the route named '/'

    // 设置路由表
    // 访问 /a 就会跳转到 MyPage1 页面
    // 访问 /b 就会跳转到 MyPage2 页面
    // 访问 /c 就会跳转到 MyPage3 页面
    routes: <String, WidgetBuilder> {
      '/a': (BuildContext context) => new MyPage1(title: 'page A'),
      '/b': (BuildContext context) => new MyPage2(title: 'page B'),
      '/c': (BuildContext context) => new MyPage3(title: 'page C'),
    },
  ));
}

跳转到某个路由

Navigator.pushNamed(context, '/b');

完整的代码实例

import 'package:flutter/material.dart';

void main() {
  runApp(new MaterialApp(
    title: "测试",
    home: new IndexPage(),
    // 添加路由表
    routes: <String, WidgetBuilder> {
      '/a' : (BuildContext context) => new IndexPage(),
      '/b' : (BuildContext context) => new ItemPage(),
    },
  ));
}

class IndexPage extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text("第一个界面"), ),
        body: new Center(
          child: new RaisedButton(onPressed: (){
            // 使用 Navigator.pushNamed(context, '/a') 跳转
            Navigator.pushNamed(context, '/b');
          }, child: new Text("点击跳转到第二个界面"),),
        )
    );
  }
}

class ItemPage extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(title: new Text("第二个界面"), ),
        body: new Center(
          child: new RaisedButton(onPressed: (){
            Navigator.pushNamed(context, '/a');
          }, child: new Text("点击跳转到第一个界面"),),
        )
    );
  }
}

图示:

Flutter学习之路由与导航-LMLPHP

10-03 14:52