目录
目录21 | 路由与导航,实现页面切换
如果说 UI 框架的视图元素的基本单位是组件
,那应用程序的基本单位就是页面
了。对于拥有多个页面的应用程序而言,如何从一个页面平滑地过渡到另一个页面,我们需要有一个统一的机制来管理页面之间的跳转,通常被称为路由
管理或导航
管理。
我们首先需要知道目标页面对象,在完成目标页面初始化后,用框架提供的方式打开它。比如,在 Android/iOS 中我们通常会初始化一个 Intent 或 ViewController,通过 startActivity 或 pushViewController 来打开一个新的页面;而在 React 中,我们使用 navigation 来管理所有页面,只要知道页面的名称,就可以导航到这个页面。
路由管理
在 Flutter 中,页面之间的跳转是通过 Route 和 Navigator 来管理的:
- Route 是页面的抽象,主要负责创建对应的界面,接收参数,响应 Navigator 打开和关闭
- Navigator 会维护一个路由栈管理 Route 的入栈/出栈,还可以直接替换栈内的某一个 Route
根据是否需要提前注册页面标识符,Flutter 中的路由管理可以分为两种方式:
- 基本路由:无需提前注册,在页面切换时需要自己构造页面实例
- 命名路由:需要提前注册页面标识符,在页面切换时通过标识符直接打开新的路由
基本路由
在 Flutter 中,基本路由的使用方法和 Android/iOS 打开新页面的方式非常相似:
- 要导航到一个新页面,需要创建一个 Route,调用
Navigator.push
将新页面压到栈顶 - 要返回到上一个页面,需要调用
Navigator.pop
方法,将栈顶的页面从堆栈中删除
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.title)),
body: Text(widget.title),
floatingActionButton: FloatingActionButton(
onPressed: _onPressed,
child: Text(widget.title),
));
}
void _onPressed() {
if (widget.title == "白乾涛") {
Route<HomePage> route = MaterialPageRoute(builder: (context) => const HomePage(title: "页面2"));
Navigator.push(context, route);
} else {
Navigator.pop(context);
}
}
}
MaterialPageRoute 是一种路由模板,定义了路由创建及切换过渡动画的相关配置,可以针对不同平台,实现与平台页面切换动画风格一致的路由切换动画。
命名路由
基本路由适用于应用中页面不多的场景。在应用中页面比较多的情况下,Flutter 提供了另外一种方式来简化路由管理,即命名路由。我们给页面起一个名字,然后就可以直接通过页面名字打开它了。
路由表 routes
要想通过名字来指定页面切换,我们必须先给应用程序 MaterialApp 提供一个页面名称映射规则,即路由表 routes
,这样 Flutter 才知道名字与页面 Widget 的对应关系。
路由表 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: (RouteSettings 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())); // 设置目标页面关闭时的监听函数
}
}
页面参数
Flutter 提供了路由参数的机制,可以在打开路由时传递相关参数,在目标页面通过 RouteSettings
获取页面参数。
启动参数
// 传递参数
Navigator.pushNamed(context, routeName, arguments: "[from: ${widget.title}]");
Navigator.of(context).pushNamed(routeName, arguments: "from ${widget.title}");
// 取出参数
Object? arguments = ModalRoute.of(context)?.settings.arguments;
返回参数
与 Android 提供的 startActivityForResult
方法可以监听目标页面的处理结果类似,Flutter 也提供了返回参数的机制。在 push
目标页面时,可以设置目标页面关闭时的监听函数,以获取返回参数;而目标页面可以在关闭路由时传递相关参数。
下面的代码演示了如何获取参数:在 SecondPage 页面关闭时,传递了一个字符串参数,随后在上一页监听函数中,我们取出了这个参数,并将它展示了出来。
// 设置目标页面关闭时的监听函数
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
标签:21,title,Route,陈航,参数,context,Navigator,路由,页面 From: https://www.cnblogs.com/baiqiantao/p/17033850.html