Flutter-路由和导航

一、前言

在Android开发中,界面的跳转使用的Context.startActivity来实现,界面通常指的Activity,如果我们的设计是单Activity+Fragment来实现,界面的跳转就需要使用FragmentManager来完成。这些概念到了Flutter中有了一些变化。

二、路由是什么

我们通常使用“屏”来展示应用的不同页面(界面)。比如应用有一屏展示商品列表,点击Item的时候,跳转到新的一“屏”展示商品的详细信息。

在Flutter中,屏(screen)页面(page) 都叫做 路由(route)

因此, 在后期的开发中,我们基本都会建一个screen或者page的文件夹,里面文件代表一屏需要展示的界面。当前文件的命名也可以加一个screen或者page的后缀,比如login_page.dart 或 login_screen.dart

所以在后面的界面跳转或者页面跳转都值的是路由的跳转,那么如何从一个‘路由’跳转到一个新的路由呢

三、使用Navigator来实现路由的的跳转功能

在Flutter中,封装了Navigator来实现界面的跳转功能,接下来了解具体的使用。

3.1 使用Navigator.push()跳转到一个新的路由

push()方法需要传入Route对象,随后将Route对象添加到导航器的堆栈上。这里的Route对象我们可以自己实现,当前前期入门的时候,推荐使用MaterialPageRoute,框架已经实现了和平台原生动画类似的动画切换。

    Navigator.push(context,
        MaterialPageRoute(builder: (context) => const TestPageTwo()));

当然这里我们可以使用Navigator.of(context).push()方法。完成的效果图如下:

image

3.2 使用Navigator.pop()回退到上一个路由

Flutter中使用Navigator.pop()方法,将到导航器堆栈上的Route对象移除。

下面在test_page2上添加一个回退功能

    child: ElevatedButton(
      onPressed: () {
        Navigator.pop(context);
      },
      child: const Text('页面2返回按钮'),
    ),

3.3 传递数据到新页面

在开发中,进程会遇到需要在跳转新页面的时候传递一些数据的,比如从待办列表页到待办详情页,需要传递待办数据id或者更多的信息。

传递参数有两种方式,框架提供了两种方式:构造函数或者RouteSettings,下面分别介绍这两种方式的使用。

3.3.1 传递数据到新页面-通过构造函数方式传递数据

通过构造函数的方式相对简单,在对应的widget构造函数中添加参数即可,如:

class TestPageTwo extends StatelessWidget {

  final ToDo todo;

  const TestPageTwo({Key? key,required this.todo}) : super(key: key);
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('界面2'),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('界面传递数据:${todo.title},${todo.description}'),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
              },
              child: const Text('页面2返回按钮'),
            ),
          ],
        ),
      ),
    );
  }  
  
}
3.3.2 传递数据到新页面-使用RouteSettings的方式传递参数

使用RouteSettings ,在创建MaterialPageRoute时添加setting参数,如下所示:

 onPressed: () {
            Navigator.push(
                context,
                MaterialPageRoute(
                    settings: RouteSettings(arguments: ToDo(1, '今日待办', '今日事今日毕')),
                    builder: (context) => const TestPageTwo()));
          },

这里如果使用Navigator.pushNamed()方法可以直接传递参数Navigator.pushNamed(context, ‘routeName’,arguments: ToDo());这里命名路由的方式后续讲。

提取RouteSettings传递过来的参数

class TestPageTwo extends StatelessWidget {

  const TestPageTwo({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    
   final todo =  ModalRoute.of(context)!.settings.arguments as ToDo;
   
   ......
   
  }

向新页面传递参数,上述两种方式都合适,根据自己的喜好使用即可。但是如果使用命名路由 后则会使用RouteSettings。Navigator.pushNamed()方法中的arguments也转化为了Routesettings对象。

3.4 从一个页面返回数据

在Android中,有startActivityForResult的方式获取页面返回的参数,在Flutter中则更简单一些。

3.4.1 Navigator.pop()方法中加入返回数据
Navigator.pop(context,'返回数据');
3.4.2 Navigator.push时获取返回数据

Navigator.push返回一个Future,异步操作需要结合async和await关键字,更多的用法需要参考dart的异步操作。

  _navigateToSecondPage(BuildContext context) async{
   final result = await Navigator.push(
        context,
        MaterialPageRoute(
            settings: RouteSettings(arguments: ToDo(1, '今日待办', '今日事今日毕')),
            builder: (context) => const TestPageTwo()));

   print('$result');
  }

3.5 使用命名路由的方式进行界面跳转

前面界面跳转方式和Android原生的基本一致,Flutter还支持命名路由的方式进行跳转,这样可以减少代码的重复以及文件之间的相互引用关系。

3.5.1 配置命名路由

命名路由的配置需要在MaterialApp中的routes参数中进行配置,如下:

return MaterialApp(
    ......
    routes:{
        'secondPage': (context) => const TestPageTwo(),
    },

)

平时开发中我们都不会直接在这里进行配置,单独放在一个文件中进行配置,例如在routes.dart文件中添加以下代码:

class Routes {
  static const initialRoute = '/';
  static const routeSecondPage = '/secondPage';

  static final routes = {
    initialRoute: (context) => const TestPageOne(),
    routeSecondPage: (context) => const TestPageTwo()
  };
}

接下来修改MaterialApp:

    return MaterialApp(
      ......
      routes: Routes.routes,
      initialRoute: Routes.initialRoute,
    );

注意

使用 initialRoute 时,需要确保你没有同时定义 home 属性。

3.5.2 使用命名路由

使用命名路由则使用Navigator.pushNamed()方法。

Navigator.pushNamed(context, Routes.routeSecondPage)
3.5.3 传递参数
  _navigateToSecondPage(BuildContext context) async {
    var param = ToDo(1, '今日待办', '今日事今日毕');
    final result = await Navigator.pushNamed(context, Routes.routeSecondPage,
        arguments: param);
    print('$result');
  }
3.5.4 获取参数
class TestPageTwo extends StatelessWidget {

  const TestPageTwo({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    
   final todo =  ModalRoute.of(context)!.settings.arguments as ToDo;
   
   ......
   
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值