> 文档中心 > Flutter基础(一)页面跳转

Flutter基础(一)页面跳转


一、介绍

在安卓里,界面(Activity)的跳转是通过startActivity来完成。而在Flutter里,把界面称作为一个个Route,他们的跳转是通过一个叫做路由管理(Navigator)的工具,负责页面之前的跳转,包括参数的传递接受和返回。Navigator的方法总的来说就两个,push(进栈),pop(出栈),跟Activity一样也会生成一个存放页面的栈。

二、页面跳转

首先,我们创建一个新的页面,如下

class TwoPageRoute extends StatelessWidget {  const TwoPageRoute({Key? key,}) : super(key: key);  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar( title: const Text("第二个页面"),      ),    );  }}
2.1 普通跳转

可以看到,在界面添加了跳转到TwoPageRoute页面的按钮。

TextButton(  child: const Text("通过实例跳转"),  onPressed: ()  {   Navigator.push(context, MaterialPageRoute(builder: (context) {      return const TwoPageRoute();    }));  },)

**提示1:**关于MaterialPageRoute可以理解为对路由界面的一个封装,继承于PageRoute,定义了页面之前跳转的动画,可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。

**提示2:**在Flutter中,如果代码是固定的,也就是写死的,编译器会建议加上const。如果你是通过值传递的,那自然就不能加const了。

2.2 参数跳转

界面的跳转中,经常都需要传递参数。下面我们传递一个String参数和一个Bean类

UserBean类

class UserBean{   String name;   int age;   UserBean(this.name, this.age);}

修改TwoPageRoute页面

class TwoPageRoute extends StatelessWidget {  const TwoPageRoute({Key? key,    required this.text, // 接收一个text参数    required this.userBean //接收一个userBean类  }) : super(key: key);  final String text;  final UserBean userBean;  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar( title: const Text("第二个页面"),      ),      body: Center( child: Column(   children: [     Text("接受text值:$text"),     Text("接受userBean值:${userBean.toString()}"),   ], ),      ),    );  }}

修改TextButton中的传参

TextButton(  child: const Text("通过实例跳转"),  onPressed: ()  {   Navigator.push(context, MaterialPageRoute(builder: (context) {      return TwoPageRoute(   text: "我是第一个页面", userBean: UserBean("小小虫", 18));    }));  },)
2.2 接收参数返回

在Flutter,接受页面的返回参数,相比安卓会比较方便,如下:

TextButton(  child: const Text("通过实例跳转"),  onPressed: () async {    var result = await Navigator.push(context, MaterialPageRoute(builder: (context) {      return TwoPageRoute(   text: "我是第一个页面", userBean: UserBean("小小虫", 18));    }));    print("路由返回值: $result");  },)

修改TwoPageRoute页面,添加一个按钮返回参数

TextButton(    onPressed: () {      Navigator.pop(context, "我是返回值");    },    child: const Text("关闭页面并返回值"))

**注意1:**关键词async和await,不然不会等待页面结束接受返回值。关键词async和await,不然不会等待页面结束接受返回值。

三、路由命名跳转

​ 在Flutter中,页面的跳转除了通过上面的方法外,还有一种通过路由命名跳转,类似于安卓的隐式跳转,安卓的如下:

<action android:name="com.example.SplashActivity" />

而在Flutter中,需要在MyApp中添加routes参数,如下:

void main() {  runApp(const MyApp());}class MyApp extends StatelessWidget {  const MyApp({Key? key}) : super(key: key);  @override  Widget build(BuildContext context) {    return MaterialApp(      title: 'Flutter Demo',      theme: ThemeData( primarySwatch: Colors.blue,      ),      home: const MyHomePage(title: 'Flutter Demo Home Page'),      //注册路由表      routes: { "custom_page": (context) =>  const CustomRoute(),      },    );  }}

增加一个TextButton,可以看到,路由命名的跳转需要通过pushNamed方法,支持arguments传参,是不是很熟悉的样子👀

TextButton(  child: const Text("通过自定义命名路由跳转"),  onPressed: () async {    var result = await Navigator.pushNamed(context, "custom_page", arguments: "hello,我是通过自定义命名路由跳转");    print("通过自定义命名路由跳转路由返回值: $result");  },)

然后修改CustomRoute页面,在build中获取参数,如下:

@overrideWidget build(BuildContext context) {  //获取路由参数  var args=ModalRoute.of(context)?.settings.arguments;  }

如果你想两种结合在一起,把TwoPageRoute也加到routes中,还是最好不要吧🤣

修改routes,增加two_page_route

routes: {  "two_page_route": (context) {    dynamic obj =  ModalRoute.of(context)!.settings.arguments;    return TwoPageRoute(text: obj["text"],userBean:obj["user"] ,);  },}

修改参数,flutter的arguments的类型真的是很百变👍,感觉出问题的几率也会很高。

TextButton(  child: const Text("通过自定义命名路由跳转"),  onPressed: () async {    var result = await Navigator.pushNamed(context, "two_page_route", arguments: {   'text': '我是第一个页面',   'user': UserBean("小小虫", 181), });    print("通过自定义命名路由跳转路由返回值: $result");  },)

四、路由钩子

​ 所谓的路由钩子,其实就是一些路由相关的监听方法(监听就监听,还钩子)。

例如:

  • onGenerateRoute:通过命名路由打开是会被调用。注意!重点!重点!是对应的name没有在routes中有映射关系,那么就会执行onGenerateRoute钩子函数,也就是没有在routes中注册路由。
  • onUnknowRoute:在打开一个不存在的命名路由时会被调用
  • navigatorObservers:监听所有路由跳转动作

举几个栗子

onGenerateRoute使用,在MaterialApp中添加onGenerateRoute,如下:

@override  Widget build(BuildContext context) {    return MaterialApp(      onGenerateRoute: (RouteSettings settings) { var routeName = settings.name; var isLogin = true; if(routeName == "two_page_route" && isLogin){   return MaterialPageRoute(builder: (context) {     return TwoPageRoute(text: "我是第一个页面", userBean: UserBean("小小虫", 18));   }); }else{   //登录逻辑。。。 }      },    );  }}

**注意:**记得先把two_page_route从routes去掉!

navigatorObservers使用,在MaterialApp中添加navigatorObservers,如下:

  @override  Widget build(BuildContext context) {    return MaterialApp(      //监听所有路由跳转动作,      navigatorObservers: [ MyNavigator()      ],    );  }

新建一个MyNavigator类,如下:

import 'package:flutter/widgets.dart';///导航栈的变化监听class MyNavigator extends NavigatorObserver{  @override  void didPush(Route route, Route? previousRoute) {    super.didPush(route, previousRoute);//监听每个路由进栈  }  @override  void didPop(Route route, Route? previousRoute) {    super.didPop(route, previousRoute);    //监听每个路由出栈  }}

空气商城