Flutter 陈航 21-路由 导航 Route Navigator 页面参数
目录
21 | 路由与导航,实现页面切换
如果说 UI 框架的视图元素的基本单位是组件
,那应用程序的基本单位就是页面
了。对于拥有多个页面的应用程序而言,需要有一个统一的机制来管理页面之间的跳转,这个机制通常被称为路由管理
或导航管理
。
路由管理
在 Android/iOS 中,通常会初始化一个 Intent/ViewController,并通过 startActivity/pushViewController 打开一个新的页面;在 React 中,则使用 navigation 来管理所有页面,只要知道页面的名称,就可以导航到这个页面。
在 Flutter 中,页面之间的跳转是通过 Route 和 Navigator 来管理的:
- Route:页面的抽象,主要负责创建界面、接收参数、响应 Navigator 的打开和关闭
- Navigator:负责路由栈的管理,例如 Route 的入栈/出栈、替换栈内的某个 Route
根据是否需要提前注册页面标识符,Flutter 中的路由管理可以分为两种方式:
- 基本路由:无需提前注册,在页面切换时需要自己构造页面实例
- 命名路由:需要提前注册,在页面切换时通过页面标识符打开新的路由
基本路由
基本路由适用于应用中页面不多的场景。
类似 Android 中的显式意图,即直接指定要跳转的目标 Activity
在 Flutter 中,基本路由的使用方法和 Android/iOS 中打开新页面的方式非常相似:
- 要导航到一个新页面,需要创建一个 Route,调用
Navigator.push
将新页面压到栈顶 - 要返回到上一个页面,需要调用
Navigator.pop
方法,将栈顶的页面从路由栈中删除
// 导航到一个新页面
Route<HomePage> route = MaterialPageRoute(builder: (context) => const HomePage(title: "页面2"));
Navigator.push(context, route);
// 返回到上一个页面
Navigator.pop(context);
MaterialPageRoute 是一种路由模板,定义了路由创建、切换过渡动画的相关配置,可以实现与当前平台风格一致的路由切换动画。
命名路由
在应用中页面较多的场景,Flutter 提供了另外一种方式来简化路由管理,即命名路由。
类似 Android 中的隐式意图,即不指定要跳转的目标 Activity,而是通过各种 Scheme 来匹配
命名路由最重要的作用,是建立了字符串标识符与各个页面之间的映射关系,使得各个页面之间完全解耦,应用内页面的切换只需要通过一个字符串标识符就可以搞定,为后期模块化打好基础。
路由表 routes
要想通过名字来切换页面,必须先给应用程序 MaterialApp 提供一个页面与名称的映射规则,即路由表 routes
。
路由表 routes 的类型是 Map<String, WidgetBuilder>
:
- key:对应页面名字,定义好后,就可以使用
Navigator.pushNamed
来打开页面了 - value:是一个
WidgetBuilder
回调函数,需要在这个函数中创建对应的页面
Flutter 提供了 onUnknownRoute
属性,可以对未知的路由标识符进行统一的页面跳转处理。
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => MaterialApp(
home: const HomePage(title: "白乾涛"),
routes: {
"first_page": (context) => const HomePage(title: "first_page"),
"second_page": (context) => const HomePage(title: "second_page"),
},
onUnknownRoute: (setting) => MaterialPageRoute(builder: (context) => const UnknownPage()),
);
}
页面 Page
class HomePage extends StatefulWidget {
final String title;
const HomePage({super.key, required this.title});
@override
State<HomePage> createState() => HomePageState();
}
class UnknownPage extends StatelessWidget {
const UnknownPage({super.key});
@override
Widget build(BuildContext context) => const Text("UnknownPage,统一的错误路由页");
}
Navigator.pushNamed
class HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
Object? arguments = ModalRoute.of(context)?.settings.arguments; // 取出参数
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: GestureDetector(
child: Text("${widget.title}\narguments = $arguments"),
onTap: () => Navigator.pop(context, "finished from ${widget.title}"), // 页面关闭时传递参数
),
floatingActionButton: FloatingActionButton(onPressed: _onPressed),
);
}
void _onPressed() {
String routeName = "未知路由";
if (widget.title == "白乾涛") {
routeName = "first_page";
} else if (widget.title == "first_page") {
routeName = "second_page";
}
flog("widget.title = ${widget.title}, routeName = $routeName");
//Navigator.pushNamed(context, routeName);
var future = Navigator.pushNamed(context, routeName, arguments: "[from: ${widget.title}]"); // 页面启动时传递参数
future.then((msg) => flog(msg.toString())); // 设置目标页面关闭时的监听函数
}
}
页面参数
在打开路由时,可以传递相关参数,并在目标页面通过 RouteSettings
获取页面参数。
启动参数
// 命名路由 传递参数
Navigator.pushNamed(context, routeName, arguments: "[from: ${widget.title}]");
Navigator.of(context).pushNamed(routeName, arguments: "from ${widget.title}");
// 基本路由 传递参数
Route<HomePage> route = MaterialPageRoute(
builder: (context) => const HomePage(title: "页面2"),
settings: const RouteSettings(arguments: "[from: ${widget.title}]"),
);
Navigator.push(context, route);
// 取出参数
Object? arguments = ModalRoute.of(context)?.settings.arguments;
返回参数
与 Android 提供的 startActivityForResult
方法可以监听目标页面的处理结果类似,Flutter 也提供了返回参数的机制。 在 push
目标页面时,可以设置目标页面关闭时的监听函数,以获取目标页面在关闭路由时传递的参数。
// 设置目标页面关闭时的监听函数,以获取目标页面在关闭路由时传递的参数
Navigator.pushNamed(context, routeName).then((msg) => flog(msg.toString()));
// 在页面关闭时传递参数
Navigator.pop(context, "finished from ${widget.title}")
总结
Flutter 提供了基本路由和命名路由两种方式来管理页面间的跳转。其中,基本路由需要自己手动创建页面实例,通过 Navigator.push
完成页面跳转;而命名路由需要提前注册页面标识符和页面创建方法,通过 Navigator.pushNamed
传入标识符实现页面跳转。
Flutter 提供了页面打开与页面关闭的参数机制,可以在页面创建和目标页面关闭时,取出相应的参数。
2023-1-7
本文来自博客园,作者:白乾涛,转载请注明原文链接:https://www.cnblogs.com/baiqiantao/p/17033850.html