Flutter 中的多个导航器导致弹出问题

Posted

技术标签:

【中文标题】Flutter 中的多个导航器导致弹出问题【英文标题】:Multiple navigators in Flutter causes problem with pop 【发布时间】:2021-02-21 13:57:57 【问题描述】:

我在多个导航器的 Flutter 情况下苦苦挣扎。这里的概念是一个页面,它通过他自己的多个页面流触发一个模式。在模式中,一切都在迅速进行(导航推送/弹出正在工作),但如果模式被关闭,它会删除最低导航器的每一页。我看过https://***.com/a/51589338 的例子,但我可能在这里遗漏了一些东西。

页面内有一个包装小部件,它是应用程序的根。

class Wrapper extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Container(
      child: Padding(
        padding: EdgeInsets.only(top: 10, bottom: 20),
        child: FlatButton(
          child: Padding(
            padding: EdgeInsets.symmetric(vertical: 5),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Text(
                  'Open modal',
                ),
              ],
            ),
          ),
          onPressed: () 
            Navigator.of(context).push(
              MaterialPageRoute(
                settings: RouteSettings(name: '/modal'),
                builder: (context) => Modal(),
              ),
            );
          ,
        ),
      ),
    );
  

模态使用他自己的导航器启动一个 Scaffold 来处理它自己的流程。

class Modal extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: new Navigator(
        initialRoute: FirstModalPage.route().toString(),
        onGenerateRoute: (routeSettings) 
          final path = routeSettings.name;
          if (path == '/secondmodalpage') 
            return MaterialPageRoute(
              settings: routeSettings,
              builder: (_) => SecondModalPage(),
            );
          

          return new MaterialPageRoute(
            settings: routeSettings,
            builder: (_) => FirstModalPage(),
          );
        ,
      ),
    );
  

模态框内的页面下方带有一个关闭按钮,该按钮应从根导航器中删除模态框。但是由于某种原因,如果我调用pop(),它会从小部件树中删除所有页面。而popUntil((route) => route.isFirst) 根本不做任何事情。如果我通过 Widget Inspector 查看小部件,它确实会说 Wrapper 和 Modal 处于同一级别。

class FirstModalPage extends StatelessWidget 
  static Route route() 
    return MaterialPageRoute<void>(builder: (_) => FirstModalPage());
  

  @override
  Widget build(BuildContext context) 
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.only(
              top: 30,
              right: 20,
              bottom: 10,
              left: 20,
            ),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                GestureDetector(
                  behavior: HitTestBehavior.translucent,
                  onTap: () 
                    if (Navigator.of(context).canPop()) 
                      Navigator.of(context).pop();
                    
                  ,
                  child: Text('Back'),
                ),
                Text(
                  'First modal page title'
                ),
                GestureDetector(
                  behavior: HitTestBehavior.translucent,
                  onTap: () 
                    Navigator.of(context, rootNavigator: true).popUntil(
                      (route) => route.isFirst,
                    );
                  ,
                  child: Text('Close'),
                ),
              ],
            ),
          ),
          FlatButton(
            onPressed: () 
              Navigator.of(context).push(
                MaterialPageRoute(builder: (context) => SecondModalPage()),
              );
            ,
            child: Text(
              'Second modal page'
            ),
          ),
        ],
      ),
    );
  

【问题讨论】:

【参考方案1】:

您需要使用 Navigator 键来密切关注您需要使用哪个 Navigator 执行操作。

final _mainNavigatorKey = GlobalKey<NavigatorState>();

Navigator(
  key: _mainNavigatorKey,
  ...
),

要使用导航键,您可以拨打_mainNavigatorKey.currentState.pop();

【讨论】:

以上是关于Flutter 中的多个导航器导致弹出问题的主要内容,如果未能解决你的问题,请参考以下文章

如何在 2.5 版本的新 Flutter 模板上集成底部导航栏?

Flutter:导航时“小部件树中的多个全局键”

Flutter:如何在抽屉内推送/弹出导航器页面?

Flutter学习笔记--仿闲鱼底部导航栏带有中间凸起图标

Flutter 嵌套声明式导航

Dismissible confirmDismiss 结合新的路由导航导致 Flutter 崩溃