Flutter如何创建一个内嵌的navigation

其他教程   发布日期:2023年08月23日   浏览次数:460

这篇文章主要讲解了“Flutter如何创建一个内嵌的navigation”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Flutter如何创建一个内嵌的navigation”吧!

简介

我们在flutter中可以使用Navigator.push或者Navigator.pushNamed方法来向Navigator中添加不同的页面,从而达到页面调整的目的。

一般情况下这样已经足够了,但是有时候我们有多个Navigator的情况下,上面的使用方式就不够用了。比如我们有一个主页面app的Navigator,然后里面有一个匹配好友的功能,这个功能有多个页面,因为匹配好友功能的多个页面实际上是一个完整的流程,所以这些页面需要被放在一个子Navigator中,并和主Navigator区分开。

那么应该如何处理呢?

搭建主Navigator

主Navigator是我们app的一些主要界面,这里我们有三个界面,分别是主home界面,一个setting配置界面和好友匹配界面。

其中好友匹配界面包含了三个子界面,这三个子界面将会用到子路由。

先来看下主路由,主路由的情况跟普通的路由没啥区别,这里我们首先定义和home和setting匹配的两个widget:HomePage和SettingsPage:

  1. class HomePage extends StatelessWidget {
  2. const HomePage({
  3. super.key,
  4. });
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: _buildAppBar(context),
  9. body: Center(
  10. child: Padding(
  11. padding: const EdgeInsets.symmetric(horizontal: 24.0),
  12. child: Column(
  13. mainAxisSize: MainAxisSize.min,
  14. children: const [
  15. SizedBox(
  16. width: 250,
  17. height: 250,
  18. child: Center(
  19. child: Icon(
  20. Icons.home,
  21. size: 175,
  22. color: Colors.blue,
  23. ),
  24. ),
  25. ),
  26. SizedBox(height: 32),
  27. Text(
  28. '跳转到好友匹配页面',
  29. textAlign: TextAlign.center,
  30. style: TextStyle(
  31. fontSize: 24,
  32. fontWeight: FontWeight.bold,
  33. ),
  34. ),
  35. ],
  36. ),
  37. ),
  38. ),
  39. floatingActionButton: FloatingActionButton(
  40. onPressed: () {
  41. Navigator.of(context).pushNamed(routeFriendMatch);
  42. },
  43. child: const Icon(Icons.add),
  44. ),
  45. );
  46. }

HomePage很简单,它包含了一个floatingActionButton,当点击它的时候会调用 Navigator.pushNamed方法进行路由切换。

然后是SettingsPage,它是一个简单的Column:

  1. class SettingsPage extends StatelessWidget {
  2. const SettingsPage({
  3. super.key,
  4. });
  5. @override
  6. Widget build(BuildContext context) {
  7. return Scaffold(
  8. appBar: _buildAppBar(),
  9. body: SingleChildScrollView(
  10. child: Column(
  11. mainAxisSize: MainAxisSize.min,
  12. children: List.generate(8, (index) {
  13. return ListTile(
  14. title: Text('设置项$index'),
  15. );
  16. }),
  17. ),
  18. ),
  19. );
  20. }

最后一个页面是FriendMatchFlow,这个页面比较复杂,我们在下一个再进行讲解。

然后我们为主路由在onGenerateRoute方法中进行定义:

  1. void main() {
  2. runApp(
  3. MaterialApp(
  4. onGenerateRoute: (settings) {
  5. late Widget page;
  6. if (settings.name == routeHome) {
  7. page = const HomePage();
  8. } else if (settings.name == routeSettings) {
  9. page = const SettingsPage();
  10. } else if (settings.name == routeFriendMatch) {
  11. page = const FriendMatchFlow(
  12. setupPageRoute: routeFriendMatchPage,
  13. );
  14. }
  15. return MaterialPageRoute<dynamic>(
  16. builder: (context) {
  17. return page;
  18. },
  19. settings: settings,
  20. );
  21. },
  22. debugShowCheckedModeBanner: false,
  23. ),
  24. );
  25. }

主路由很简单,跟普通的路由没有太多的区别。

构建子路由

接下来是构建子路由的步骤。在主路由中,如果路由的名称是routeFriendMatch,那么就会跳转到FriendMatchFlow。

而这个flow页面实际上是由几个子页面组成的:选择好友页面,等待页面,匹配页面和匹配完毕页面。

具体的页面代码这里就不写了,我们主要来讲一下子路由的使用。

对于FriendMatchFlow来说,它本身是一个Navigator,所以我们的build方法是这样的:

  1. Widget build(BuildContext context) {
  2. return WillPopScope(
  3. onWillPop: _isExitDesired,
  4. child: Scaffold(
  5. appBar: _buildFlowAppBar(),
  6. body: Navigator(
  7. key: _navigatorKey,
  8. initialRoute: widget.setupPageRoute,
  9. onGenerateRoute: _onGenerateRoute,
  10. ),
  11. ),
  12. );
  13. }

因为他需要根据用户的不同点击来进行内部路由的切换,所以需要保存对当前子Navigator的应用,所以这里FriendMatchFlow是一个StatefulWidget,并且上面的_navigatorKey是一个GlobalKey对象,以提供对子Navigator的引用:

  1. final _navigatorKey = GlobalKey<NavigatorState>();

这里的_onGenerateRoute方法,跟主路由也是很类似的,主要定义的是子路由中页面的跳转:

  1. Route _onGenerateRoute(RouteSettings settings) {
  2. late Widget page;
  3. switch (settings.name) {
  4. case routeFriendMatchPage:
  5. page = WaitingPage(
  6. message: '匹配附近的好友...',
  7. onWaitComplete: _onDiscoveryComplete,
  8. );
  9. break;
  10. case routeFriendSelectPage:
  11. page = SelectFriendPage(
  12. onFriendSelected: _onFriendSelected,
  13. );
  14. break;
  15. case routeFriendConnectingPage:
  16. page = WaitingPage(
  17. message: '匹配中...',
  18. onWaitComplete: _onConnectionEstablished,
  19. );
  20. break;
  21. case routeFriendFinishedPage:
  22. page = FinishedPage(
  23. onFinishPressed: _exitSetup,
  24. );
  25. break;
  26. }

这里的on***Selected是VoidCallback回调,用来进行路由的切换:

  1. void _onDiscoveryComplete() {
  2. _navigatorKey.currentState!.pushNamed(routeFriendSelectPage);
  3. }
  4. void _onFriendSelected(String deviceId) {
  5. _navigatorKey.currentState!.pushNamed(routeFriendConnectingPage);
  6. }
  7. void _onConnectionEstablished() {
  8. _navigatorKey.currentState!.pushNamed(routeFriendFinishedPage);
  9. }

可以看到上面的路由切换实际上是在子路由上切换,跟父路由无关。

如果想要直接从子路由跳出到父路由该怎么处理呢?很简单,调用Navigator.of的pop方法即可:

  1. void _exitSetup() {
  2. Navigator.of(context).pop();
  3. }

这里的context默认是全局的context,所以会导致主路由的跳转变化。

以上就是Flutter如何创建一个内嵌的navigation的详细内容,更多关于Flutter如何创建一个内嵌的navigation的资料请关注九品源码其它相关文章!