Flutter探索(六) -- 路由学习

今天学习下Flutter的界面跳转,也就是路由的运用,首先我们需要创建两个界面LoginPageMenuPage,然后把登录界面设为主界面,菜单界面设置为二级界面,我们有登录界面跳转到菜单界面:

// 登录界面
class LoginPage extends StatelessWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("登录"),
      ),
      body: TextButton(
        onPressed: () {
        // Navigator 路由
        // 跳转代码
        },
        child: const Text("登录"),
      ),
    );
  }
}

// 二级界面
class MenuPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    dynamic arguments = ModalRoute.of(context)?.settings.arguments;
    print(arguments);
    return Scaffold(
      appBar: AppBar(
        title: Text("menu"),
      ),
    );
  }
}

我们把登录界面设置为主界面:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: LoginPage(), // 设置主界面
    );
  }
}

下面介绍几种路由跳转:

一、 路由的普通跳转

我们使用Navigator进行界面的跳转,我们在LoginPage的点击事件中写跳转代码,如下:

// Navigator 路由
 // 跳转代码
Navigator.of(context).push(MaterialPageRoute(
            builder: (context) {
              return const MenuPage();
            },
            // settings 会改一些路由的名称、参数 或者设置它跳转以后是不是新的主界面(就是有没有返回按钮)
            settings: const RouteSettings(
              name: "你好",
              arguments: "",
            ),
            // 跳转以后之前的路由是否要释放 false - 释放 ,true - 不释放
            maintainState: false,
            // 跳转之后是否是全屏的 flase(push跳转) 和 true(模态跳转) 转场动画不一样
            fullscreenDialog: true,
          ));

跳转的时候我们需要用MaterialPageRoute进行包装,,MaterialPageRoute中有几个参数需要了解绍几个常用的:

  • builder: 这里面返回的就是需要跳转到的界面
  • settings: 这里可以设置路由的名称、参数 或者设置它跳转以后是不是新的主界面(就是有没有返回按钮)
  • maintainState: 设置跳转以后之前的路由是否要释放 false - 释放 ,true - 不释放
  • fullscreenDialog: 跳转之后是否是全屏的 flase(push跳转) 和 true(模态跳转) 转场动画不一样
二、路由传值
  • 组件传值
    例如:我们需要传一个名字给二级的菜单界面,那我们首先在MenuPage里写一个接收的对象:
// 接收的对象
 final String title;
 const MenuPage({Key? key, required this.title}) : super(key: key);

然后我们可以在标题赋值的时候使用title:

appBar: AppBar(
        title: Text(title),
      ),

传值的时候,我们只需要在初始化MenuPage的时候把title赋值就行了:

Navigator.of(context).push(MaterialPageRoute(
            builder: (context) {
              return const MenuPage(
              	title: "Menu",	
              );
            },
          ));

这样就会在跳转的时候把Menu这值传到MenuPage界面。

  • 参数传值
    组件传值局限性比较大,这是我们也可以用MaterialPageRoute中的settings进行传值:
Navigator.of(context)
          .push(MaterialPageRoute(
            builder: (context) {
              // 组件传值
              return MenuPage();
            },
            settings: const RouteSettings(
              name: "menu",
              // 路由传值
              arguments: "name", //也可以传对象
            ),
          ));

sttings使用的时候我们需要用RouteSettings包装,这个里面有namearguments两参数:

name:路由的名称(单独界面使用时候,可以为空,这个参数主要是为了区分不同的路由,后面封装路由的时候比较重要)
arguments:需要传的参数,这个是泛型的,可以传任意类型的数据,包括对象。

当然在MenuPage界面创建一个接收器,要不没法接收数据,我们使用ModalRoute去接收:

Widget build(BuildContext context) {
// 接收参数
    dynamic arguments = ModalRoute.of(context)?.settings.arguments;
    print(arguments);
    return Scaffold(
      appBar: AppBar(
        title: Text(arguments),
      ),
    );
  }
三、路由的返回值(反向传值)

我们有的时候,需要从二级界面回传一些值到一级界面,这时候就需要用到反向传值了,我这里介绍两种传值的方法:

  • 1、使用then进行返回值的读取,也就是在Navigator跳转方法后面添加then方法:
Navigator.of(context)
          .push(MaterialPageRoute(
            builder: (context) {
              // 组件传值
              return MenuPage();
            },
            settings: const RouteSettings(
              name: "menu",
              // 路由传值
              arguments: "name", //也可以传对象
            ),
          )).then((value) =>
          // 打印返回值
           	print(value)
           );

我们在MenuPage界面添加一个返回按钮,点击的时候,把参数传回主界面,pop返回我们需要用到Navigator中的pop方法,返回的参数就可以在pop里面添加:

body: TextButton(
        onPressed: () {
          // Navigator.of(context).pop("返回值");
          // 返回对象
          Navigator.of(context).pop({
          	"返回值"
          	// 也可以是个对象
            // "name": "返回值",
          });
        },
        child: const Text("返回"),
      ),

: 返回的不止是字符串,也可以是个对象,这是个泛型

  • 2、 异步读取
    我们也可以在跳转的时候,填个一个异步操作,我们可以对Navigator添加一个接收对象result,然后使用await进行等待读取,await修饰后,只有在有返回值得时候,才会进行下一步操作。
// 添加返回值
      body: TextButton(
        // 异步返回
        onPressed: () async {
          // await 等待,一直等到有返回值返回的时候才会走下一步 print(result);
          var result = await Navigator.of(context).push(MaterialPageRoute(
            builder: (context) {
              return  MenuPage();
            },
            // 打印返回值
            print(result);
        },
        child: const Text("登录"),
      ),
四、路由的封装(系统的)

上面介绍的方法时在每个控制器去写路由的创建,这样比较麻烦,也不好去维护和扩展,我们可以吧路由的创建全部写在main.dart里面,MaterialApp这里面有个routes参数,我们可以在这里面去添加各个控制器:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      routes: {
        "/": (context) => const LoginPage(),
        "menu": (context) => MenuPage(),
      },
      // 指定界面为主界面
      // initialRoute: "menu",
      // home: LoginPage(),
    );
  }
}
  • 使用routes的时候就不需要用home去指定主界面了。
  • routes结构是: “路由名称” : => 初始化的控制器
  • /: 如果使用斜杠为路由的名字,系统就会默认此路由是主界面
  • 当然我们也可以使用initialRoute 去指定一个路由为主界面,只需要把路由的名字赋值给它就行。

我们在MyApp里面设置玩路由之后,我们在各个控制器中使用路由的时候,只需要根据路由的名字就能跳转了:

Navigator.of(context)
              .pushNamed("menu", arguments: "menu123")
              .then((value) => print(value));

使用的时候我们需要使用pushNamed 方法根据路由的名字去跳转,arguments还是代表的需要传的参数。

这就是Flutter 路由的初步学习,至于路由更便捷的操作和路由的高级用法,后续会慢慢的研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值