flutter 路由

本文最后更新于:2022年4月22日 上午

flutter 路由

flutter中的路由和 vue中的路由有些类似,也是通过路由配置表的方式来进行设置

flutter中,路由的转场动画默认为ios端路由跳转是从右向左进入页面,android端是从底部滑到顶部的方式进入页面

配置项目路由

  • routes 路由配置表
  • onGenerateRoute 类似于vue 中的全局导航守卫,路由跳转时的钩子
  • onUnknownRoute找不到路由时的钩子,一般跳转到 404 页面
main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      initialRoute: AppRouterName.INIT_PAGE,
      routes: appRouter,
      home: HomePage(),
      // 自定义返回,类似于导航守卫
      onGenerateRoute: (settings) {
        print('settings: $settings');

        switch (settings.name) {
          case '/goodsDetail':
            return MaterialPageRoute(
              builder: (ctx) => DetailPage(),
            );
        }
      },
      // 404 路由
      onUnknownRoute: (setting) => MaterialPageRoute(builder: (ctx) => UnknownPage()),
    );
  }
}

路由配置文件

import 'package:flutter/material.dart';

import '../pages/home.dart';
import '../pages/about.dart';
import '../pages/detail.dart';

class AppRouterName {
  static const INIT_PAGE = '/home';

  static const home = '/home';
  static const detail = '/home/detail';
  static const about = '/about';
}

final Map<String, WidgetBuilder> appRouter = {
  AppRouterName.home: (ctx) => HomePage(),
  AppRouterName.detail: (ctx) => DetailPage(),
  AppRouterName.about: (ctx) => AboutPage(),
};

路由跳转

跳转的方式最主要有两种,一种是命名路由(vuereact的编程跳转都是这种),一种是匿名路由

命名路由方式跳转

通过 Navigator.of(context).pushNamed('/goodsDetail');进行跳转

ElevatedButton(
  onPressed: () {
    Navigator.of(context).pushNamed('/home/detail');
  },
  child: Text('跳转到详情页'),
)

匿名路由方式跳转

Navigator.of(context).push()进行跳转

onPressed: () {
    Navigator.of(context).push(MaterialPageRoute(builder: (context) {
      return DetailPage();
    }));
  },
  child: Text('进入详情'),
),

返回页面

返回前一页的方式很简单

Navigator.of(context).pop();

跳转时传入参数

匿名路由传参

ElevatedButton(
  onPressed: () {
    Navigator.of(context).pushNamed('/home/detail', arguments: {"id": '3306'});
  },
  child: Text('跳转到详情页'),
)

匿名路由传参

Navigator.of(context).push(MaterialPageRoute(
  builder: (context) => DetailPage(),
  settings: RouteSettings(arguments: {'id': '8000'}),
));

接收

通过 ModalRoute.of(context)!.settings.argements进行接收

@override
Widget build(BuildContext context) {
  final params = ModalRoute.of(context)!.settings.arguments as Map<String, String>;
  
  return Text('详情页 商品id:${params['id']}');
}

跳转时接收返回的参数

flutter在跳转到某个页面后,可以接收这个页面携带回来的一些参数,使用方式也很简单

接收返回的参数

ElevatedButton(
  onPressed: () async {
    // 命名路由跳转传参,可以等待返回的结果
    final res = await Navigator.of(context).pushNamed(AppRouterName.detail);
    print('接收到的结果 $res');  // 用户已操作完毕
  },
  child: Text('进入详情'),
),

返回时传入参数

Navigator.of(context).pop('用户已操作完毕');

监听页面返回

使用 Scaffold创建的页面左上角默认有一个返回按钮,点击就可以返回,如果需要监听这个返回有以下两种方式

方式一、WillPopScope

  1. 将其包裹在 Scaffold外层
  2. onWillPop方法返回一个通过Futrue 包装的 flase
  3. onWillPop手动执行 Navigator.of(context).pop()
import 'package:flutter/material.dart';

class DetailPage extends StatelessWidget {
  const DetailPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final params = ModalRoute.of(context)!.settings.arguments as Map<String, String>;

    // 捕捉返回事件
    return WillPopScope(
      onWillPop: () async {
        Navigator.of(context).pop('用户已操作完毕');
        return false;
      },
      child: Scaffold(
        appBar: AppBar(title: Text('详情页')),
        body: Container(
          child: Text('详情页 商品id:${params['id']}'),
        ),
      ),
    );
  }
}

方式二、leading

覆盖 AppBar 中的默认 leading 属性,传入一个空的 Container

Navigator 2.0 还新增了一些新的 api,但以上这些基本就够项目使用了


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处。