Flutter

[Flutter] Navigator的使用记录

2021-06-05  本文已影响0人  沉江小鱼

1. 简单的路由使用:

// 跳转到一个新的页面
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
      return HomePage();
}));

MaterialPageRoute 继承自PageRoute(抽象类),MaterialPageRouteMaterial组件库提供的组件,它可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。

构造函数:

  MaterialPageRoute({
     // 构建路由页面,返回一个widget
    WidgetBuilder builder,
    // 包含路由的配置信息,如路由名称、是否初始路由(首页)
    RouteSettings settings, 
    // 默认情况下,入栈一个新路由时,原来的路由一直保存,如果想在路由没用的时候(??)释放其资源,设置maintainState为false
    bool maintainState = true,
    // 表示新的路由页面是否是一个全屏的模态对话框,ios中如果为true,说明是模态跳转
    bool fullscreenDialog = false,
  })

可以继承PageRoute来实现自定义路由切换动画。

2. Navigator

使用栈管理路由。

2.1 基础用法:打开&关闭
// 打开新的页面,返回一个Future对象,接收新路由出栈(关闭)时的返回数据
Future push(BuildContext context, Route route)

// 关闭页面,result为返回参数
bool pop(BuildContext context, [ result ])

Navigator类中第一个参数为context的静态方法都对应一个实例方法,比如:Navigator.push(BuildContext context, Route route) 等价于 Navigator.of(context).push(Route route)

2.2 逆向传值

场景:A页面中打开B页面,B页面关闭时给A传值。

代码如下:

A页面跳转代码:
// 返回的是一个Future对象
Future future = Navigator.of(context).push(
      MaterialPageRoute(
          builder: (context) {
            return HomePage();
          },
          maintainState: false),
    );
// 获取回调过来的数据
future.then((value) {
      print(value);
});

B页面代码:
// 关闭页面
Navigator.of(context).pop("这是回调给A页面的数据");
2.3 命名路由

就是给路由起个名字,然后使用名字打开路由,更简单方便。

2.3.1 路由表

维护路由和名字的映射关系,就需要用到路由表

// value 是一个builder回调函数,用于生成相应的路由widget
Map<String, WidgetBuilder> routes;

通过路由名字打开路由时,会从路由表中查找对应的WidgetBuilder回调函数,然后调用该回调函数生成路由Widget并返回。

2.3.2 路由表注册

main.dart文件中的MaterialApp构造函数中,添加routes(注册路由表)和initialRoute(标明应用的首页):

MaterialApp(
  title: 'FlutterStudy',
  initialRoute:"/", //名为"/"的路由作为应用的home(首页)
  theme: ThemeData(
    primarySwatch: Colors.blue,
  ),
  //注册路由表
  routes:{
   "login_page": (context) => LoginPage(),
   "/":(context) => HomePage(), //注册首页路由
  } ,
);

如果使用了initialRoute指定应用首页,那么MaterialApp就不能使用home属性指定首页了,会有冲突。

2.3.3 命名路由简单使用

命名路由和普通路由的方法不同在于方法名字多了一个 named以及参数不同,很好区分,比如下面的方法:

Future pushNamed(BuildContext context, String routeName,{Object arguments})

示例:

// 通过路由名字打开路由,并传递参数
Navigator.of(context)
              .pushNamed("login_page", arguments: {"id": "111"});

// 接收参数
routes: {
    "/": (context) => HomePage(),
    "login_page": (context) {
    // 获取参数
    Map args = ModalRoute.of(context).settings.arguments;
          print(args);
          return LoginPage(id: args['id']);
        }
    },
}
2.3.4 路由生成钩子

使用场景:APP中打开某些功能需要判断是否登录,通过路由生成钩子可以统一进行处理。

MaterialApp有一个onGenerateRoute属性,当通过Navigator.pushName()打开路由时:

onGenerateRoute 只会对命名路由生效。

回调签名:

Route<dynamic> Function(RouteSettings settings)

可以不使用路由表,只使用onGenerateRoute回调,然后在该回调中进行统一的权限控制:

MaterialApp(
  ... //省略无关代码
  onGenerateRoute:(RouteSettings settings){
      return MaterialPageRoute(builder: (context){
           String routeName = settings.name;
       // 如果访问的路由页需要登录,但当前未登录,则直接返回登录页路由,
       // 引导用户登录;其它情况则正常打开路由。
     }
   );
  }
);

3. Navigator相关方法记录

3.1 常用跳转方法:
// 弹出当前页面,并跳转到一个新的页面
// A->B->C->D ,D页面调用后,A->B->C->B
Navigator.popAndPushNamed(context, 'B');

// 弹出栈中的页面,直到指定的页面
// A->B->C->D ,D页面调用后,A->B
Navigator.popUntil(context, ModalRoute.withName("B"));

// 弹出栈中的页面,直到指定的页面,然后跳转一个新页面
// A->B->C->D ,D页面调用后,A->B->F
Navigator.pushAndRemoveUntil(
              context,
              MaterialPageRoute(
                  builder: (BuildContext context) => new F()),
              ModalRoute.withName("B"));

// 和上面一样,只不过是跳转命名路由
// A->B->C->D ,D页面调用后,A->B->F
Navigator.pushNameAndRemoveUntil(
              context,
              "F"
              ModalRoute.withName("B"));

// 和上面一样,只不过是跳转命名路由
// A->B->C ,D页面调用后,A->B->D
Navigator.pushReplacementNamed(context, "D");
Navigator.pushReplacement(context, MaterialPageRoute(
                  builder: (BuildContext context) => new D()));

3.2 其他方法:
// 判断是否可以导航到新页面
canPop 
// 可能会导航到新页面
maybePop 
// 从Navigator中删除路由,同时执行Route.dispose操作。
removeRoute 
// 从Navigator中删除路由,同时执行Route.dispose操作,要替换的路由是传入参数anchorRouter里面的路由。
removeRouteBelow 
// 将Navigator中的路由替换成一个新路由。
replace 
// 将Navigator中的路由替换成一个新路由,要替换的路由是是传入参数anchorRouter里面的路由
replaceRouteBelow 

项目中使用时可以自己封装一下路由管理类,也可以使用 Fluro。本篇文章只是记录 Navigator 的一些用法,更详细的可以参考:Flutter实战:路由管理

上一篇 下一篇

猜你喜欢

热点阅读