Flutter 教程(六)路由管理

在 Flutter 中,路由管理和Android、iOS类似,都是用于管理界面之间的跳转。在 flutter 中,我们使用 Navigator 来实现跳转的功能

界面跳转

在 flutter 中,支持两种跳转方式,一种是直接跳转,一种是通过路由表跳转。下面分别介绍:

直接跳转

我们可以使用 Navigator.push 方法直接跳转到新的界面,还可以使用 Navigator.pop 回退到之前的界面。代码示例如下:

less 复制代码
Navigator.push(context, MaterialPageRoute(builder: (context) {
  return NewRoute();
}));

其中MaterialPageRoute 是 Material组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。

路由表跳转

要实现路由表跳转,我们需要先在 MaterialApp 的 routes 中注册,代码示例如下:

scala 复制代码
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      // 注册路由表
      routes: {
        'newRoute': (context) => NewRoute(),
      },
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

然后通过 Navigator.pushNamed 方法来跳转界面,代码示例如下:

arduino 复制代码
Navigator.pushNamed(context, 'newRoute');

界面之间传递参数

界面A传递数据到界面B

  • 直接跳转

对于直接跳转的情况,我们把数据传入就可以了,代码示例如下:

scala 复制代码
class NewRoute extends StatelessWidget {
  
  // 增加标题数据
  final String title;

  NewRoute({Key? key, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("New route $title"),
      ),
      body: Center(
        child: Text("This is new route"),
      ),
    );
  }
}


Navigator.push(context, MaterialPageRoute(builder: (context) {
  // 设置对应的数据
  return NewRoute(title: "新的标题",);
}));
  • 路由表跳转

对于路由表跳转,我们需要通过 ModalRoute.of(context)!.settings.arguments 来接收参数,代码示例如下:

scala 复制代码
class NewRoute extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    // 接收参数
    final args = ModalRoute.of(context)!.settings.arguments as Map<String, String>;
    final message = args['message'];
    return Scaffold(
      appBar: AppBar(
        title: Text("New route $message"),
      ),
      body: Center(
        child: Text("This is new route"),
      ),
    );
  }
}

Navigator.pushNamed(context, 'newRoute', arguments: {"title": "新的标题"});

界面B返回数据给界面A

scala 复制代码
// 设置返回值
Navigator.pop(context, "我是返回值")

class RouterTestRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: () async {
          // 打开`TipRoute`,并等待返回结果
          var result = await Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) {
                return TipRoute(
                  // 路由参数
                  text: "我是提示xxxx",
                );
              },
            ),
          );
          //输出`TipRoute`路由返回结果
          print("路由返回值: $result");
        },
        child: Text("打开提示页"),
      ),
    );
  }
}

首页

默认情况下,MaterialApp 中的 home 属性用来设置首页的界面。

scala 复制代码
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

如果你想让首页也支持路由表跳转,需要使用 initialRoute 属性,代码示例如下:

less 复制代码
MaterialApp(
  title: 'Flutter Demo',
  initialRoute:"/", //名为"/"的路由作为应用的home(首页)
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "new_page":(context) => NewRoute(),
   "/":(context) => MyHomePage(title: 'Flutter Demo Home Page'), //注册首页路由
  } 
);

其他路由方法

Navigator 除了基础的pushpop方法外,还提供了其他的方法,如下表所示:

方法名 介绍 路由关系示例 参数传递与接收
pushReplacementNamed(BuildContext context, String routeName, {Object arguments}) 使用注册的路由命名替换当前路由,从当前页面跳转到新页面,栈顶路由被替换。类似pushReplacement,只是使用路由命名而非直接路由。 当前路由顺序为A-B-C,从C执行pushReplacementNamed到D(假设D已注册路由名为"paged"),路由顺序变为A-B-D。若在D页面执行pop,路由顺序变为A-B 通过arguments参数传递数据给新页面,新页面在build方法内通过ModalRoute.of(context).settings.arguments获取参数。由于原页面已被替换,无法接收原页面返回值
popAndPushNamed<T extends Object, TO extends Object>(BuildContext context, String routeName, {TO result, Object arguments}) 当前路由出栈,同时栈顶入栈一个新路由(通过注册的路由名指定)。 当前路由顺序为A-B-C,在C页面执行popAndPushNamed到D(假设D已注册路由名为"paged"),路由顺序变为A-B-D 可通过arguments参数传递数据给新页面,新页面在build方法内通过ModalRoute.of(context).settings.arguments获取参数。result参数用于在出栈时向原页面传递数据(若有需要)
pushReplacement(BuildContext context, Route route, {TO result}) 用新路由替换当前路由,跳转到新页面,原页面被移除。 当前路由顺序为A-B-C,从C执行pushReplacement到D,路由顺序变为A-B-D。若在D页面执行pop,路由顺序变为A-B 通过目标页面的构造方法传递参数。由于原页面已被替换,无法接收原页面返回值
pushNamedAndRemoveUntil(BuildContext context, String routeName, RoutePredicate predicate, {Object arguments}) 跳转到注册路由名对应的新页面,并根据predicate的返回值决定新路由之前的路由的处理方式。类似pushAndRemoveUntil,只是使用路由命名而非直接路由。 1. 若predicate返回false,当前路由顺序为A-B-C-D-E,从E执行pushNamedAndRemoveUntil到F(假设F已注册路由名为"paged"),路由顺序变为F,A-E全部出栈。 2. 若predicate返回true,路由顺序变为A-B-C-D-E-F。 3. 若predicateModalRoute.withName指定的命名路由名称(如"pagea"),假设当前路由顺序为T-A-B-C-D,从C执行pushNamedAndRemoveUntil到D(假设D已注册路由名为"paged"),路由顺序变为T-A-D 通过arguments参数传递数据给新页面,新页面在build方法内通过ModalRoute.of(context).settings.arguments获取参数。由于原页面部分或全部被移除,无法接收原页面返回值
popUntil(BuildContext context, RoutePredicate predicate) 从栈顶开始逐个出栈路由,直到满足predicate指定的条件(条件可以是注册的路由名或RouteSetting设置的名称)。 当前路由顺序为A-B-C-D-E,在E页面执行popUntil(context, ModalRoute.withName('B')),路由顺序变为A-B 在出栈过程中,若需要传递数据给前一个页面(在满足条件停止出栈前的页面),可结合其他机制(如在相关页面的状态管理中处理)

fluro

前文介绍的所有路由知识都是Flutter官方提供的基本知识。在实际的Flutter项目中,开发人员往往并不这么写,因为还有一种更为方便的操作,也就是使用Flutter提供给我们的第三方路由库------fluro

关于 fluro 的使用,具体可以看 初识 fluro 路由管理

参考

相关推荐
孤鸿玉7 小时前
Fluter InteractiveViewer 与ScrollView滑动冲突问题解决
flutter
叽哥13 小时前
Flutter Riverpod上手指南
android·flutter·ios
BG1 天前
Flutter 简仿Excel表格组件介绍
flutter
zhangmeng1 天前
FlutterBoost在iOS26真机运行崩溃问题
flutter·app·swift
恋猫de小郭1 天前
对于普通程序员来说 AI 是什么?AI 究竟用的是什么?
前端·flutter·ai编程
卡尔特斯1 天前
Flutter A GlobalKey was used multipletimes inside one widget'schild list.The ...
flutter
w_y_fan2 天前
Flutter 滚动组件总结
前端·flutter
醉过才知酒浓2 天前
Flutter Getx 的页面传参
flutter
火柴就是我2 天前
flutter 之真手势冲突处理
android·flutter
Speed1232 天前
`mockito` 的核心“打桩”规则
flutter·dart