手记

Flutter之路由管理(页面跳转)

路由:核心是 路由映射表.
如:名字detail映射到 DetailPage页面等

在Flutter中,路由管理主要有两个类:Route和Navigator.

Route

一个页面要想被路由统一管理,必须包装为一个Route

Navigator

管理所有的Route的Widget,通过一个Stack来进行管理.

MaterialApp、CupertinoApp、WidgetsApp它们默认是有插入Navigator的,在需要的时候,只需要直接使用即可.
Navigator.of(context)

Navigator常用方法:

// 路由跳转:传入一个路由对象
Future push(Route route)

// 路由跳转:传入一个名称(命名路由)
Future pushNamed(
  String routeName, {
    Object arguments,
  })

// 路由返回:可以传入一个参数
bool pop([ T result ])

命名路由

  • 命名路由是将名字和路由的映射关系,在一个地方进行统一的管理
  • 有了命名路由,就可以通过Navigator.pushNamed()方法来跳转到新的页面

命名路由的位置

放在MaterialApp的 initialRoute 和 routes 中

  • initialRoute:设置应用程序从哪一个路由开始启动,设置了该属性,就不需要再设置home属性了

  • routes:定义名称和路由之间的映射关系,类型为 Map

  • onGenerateRoute: 通过pushNamed进行跳转,但是对应的name没有在routes中有映射关系,那么就会执行onGenerateRoute 钩子函数 . 另外, onGenerateRoute也可以作为页面跳转的权限控制.;

  • onUnknownRoute: 如果打开的一个路由名称是根本不存在的,这个时候可以跳转到一个统一的错误页面。

> 打开命名路由时,如果指定的路由名在路由表中已注册,则会调用路由表中的builder函数来生成路由组件;如果路由表中没有注册,才会调用onGenerateRoute来生成路由。

完整代码

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          primarySwatch: Colors.blue, splashColor: Colors.transparent),
      initialRoute: "/",
      routes: {
        "/": (context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
        // "/home": (ctx) => HomePage(),
        "/detail": (ctx) => DetailPage()
      },
      onGenerateRoute: (settings) {  //路由钩子 .  手动创建对应的Route进行返回;
        if (settings.name == "/about") {   //settings.name: 跳转的路径名称
          return MaterialPageRoute(builder: (ctx) {
            return AboutPage(settings.arguments);  //settings.arguments:跳转时携带的参数
          });
        }
        return null;
      },
      onUnknownRoute: (settings) {
        return MaterialPageRoute(builder: (ctx) {
          return UnknownPage();
        });
      },
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  // final message = ModalRoute.of(context).settings.arguments;

  var _message = '';

  _onPushTop(BuildContext context) {
    final future = Navigator.of(context)
        .pushNamed('/detail', arguments: "a home message of naned route"); //主动跳转时arguments传递参数

    // 2.获取结果
    future.then((res) {
      setState(() {
        _message = res;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '显示结果: ' + _message,
            ),
            FlatButton(
              child: Text("跳转下一页", style: TextStyle(color: Colors.black)),
              onPressed: () => _onPushTop(context),
            ),
            RaisedButton(
              child: Text("打开关于页"),
              onPressed: () {
                Navigator.of(context).pushNamed(AboutPage.routeName,
                    arguments: "a home message");
              },
            ),
            RaisedButton(
              child: Text("打开未知页面"),
              onPressed: () {
                Navigator.of(context).pushNamed("/abc");
              },
            ),
          ],
        ),
      ),
    );
  }
}

class DetailPage extends StatelessWidget {
  // 按钮点击执行的代码
  _onBackTap(BuildContext context) {
    Navigator.of(context).pop("a detail message");
  }

  @override
  Widget build(BuildContext context) {
	
    //接收上级页面传过来的参数
    final message = ModalRoute.of(context).settings.arguments;

    return new Scaffold(
      appBar: new AppBar(
        title: Text('这是第二页'),
        leading: IconButton(
          icon: Icon(Icons.arrow_back),
          onPressed: () {
            Navigator.of(context).pop("a back detail message"); //pop跳转时直接放入参数
          },
        ),
      ),
      body: Center(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                '首页带来的内容: ' + message,
              ),

              // child:
              RaisedButton(
                child: Text("返回首页"),
                onPressed: () => _onBackTap(context),
              ),
            ]),
      ),
    );
  }
}

class AboutPage extends StatelessWidget {
  static const String routeName = "/about";
  final String message;

  AboutPage(this.message);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("关于页面"),
      ),
      body: Center(
        child: Text(
          message,
          style: TextStyle(fontSize: 30, color: Colors.red),
        ),
      ),
    );
  }
}

class UnknownPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("错误页面"),
      ),
      body: Container(
        child: Center(
          child: Text("页面跳转错误"),
        ),
      ),
    );
  }
}
0人推荐
随时随地看视频
慕课网APP