Flutter Navigator 路由总是“/”

Posted

技术标签:

【中文标题】Flutter Navigator 路由总是“/”【英文标题】:Flutter Navigator route always "/" 【发布时间】:2021-05-28 00:50:26 【问题描述】:

我正在使用自定义 Navigator 小部件并使用 WillPopScope 包装它来处理我的应用程序中的路由。 但是在弹出或推送时,我遇到了获取堆栈顶部的确切路线的问题。我需要检测这些更改以始终在应用栏中显示当前路线名称。

我为此使用ModalRoute.of(navigatorKey.currentContext).settings.name,但打印的路线始终是“/”,即使切换页面并使用后退按钮弹出它们效果很好。

在我的main.dart 的脚手架内:

WillPopScope(
        onWillPop: () async 
          if (navigatorKey.currentState.canPop()) 

            //trying to catch name of the route during pop. results always "/"
            print(ModalRoute.of(navigatorKey.currentContext).settings.name);

            navigatorKey.currentState.pop();
            return false;
          
          return true;
        ,
        child: Navigator(
          key: navigatorKey,
          initialRoute: '/',
          onGenerateRoute: (RouteSettings settings) 

            //Each route(page) has one big button on it which leads to the next route
            //(BTW, stack is simple, linear, ProductChoice -> ShapeChoice -> ShapeEditor -> More
            // and reverse is the only possible way to navigate, for max simplicity)

            Map<String, Widget> pages = 
              "/": ProductChoice(
                navigatorKey: navigatorKey,
                swipeDownCallback: () ,
              ),
              "/shapeChoice": ShapeChoice(
                navigatorKey: navigatorKey,
                swipeDownCallback: () ,
              ),
              "/shapeEditor": ShapeEditor(
                navigatorKey: navigatorKey,
                shapeName: glassDataState.current["dimensions"]["shapeName"],
                swipeDownCallback: () ,
              ),
              "/more": More(),
            ;
            
            //Could it be pageTransition's fault? Animations seem to work fine
            return pageTransition(pages[settings.name], Offset(1, 0));
          ,
        ),
      ),

我将 navigatorKey 传递给路由,以便每条路由上的每个按钮都可以执行此操作(例如:ProductChoice):

return BigButton(
            title: title,
            onClick: () 
              navigatorKey.currentState.pushNamed("/shapeChoice");

每页还有第二个按钮,用来返回:

navigatorKey.currentState.pop();

就这么简单,但是ModalRoute.of(navigatorKey.currentContext).settings.name 到处都返回“/”。

我也试过:ModalRoute.of(context).settings.name,结果相同。

不确定pageTransition 是否重要,但无论如何:

Route pageTransition(Widget toPage, Offset begin) 
  return PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => toPage,
    transitionsBuilder: (context, animation, secondaryAnimation, child) 
      // var begin = Offset(0.0, 1.0);
      var end = Offset.zero;
      var curve = Curves.fastOutSlowIn;

      var tween = Tween(begin: begin, end: end).chain(CurveTween(curve: curve));

      return SlideTransition(
        position: animation.drive(tween),
        child: child,
      );
    ,
  );

感谢您的帮助!

【问题讨论】:

【参考方案1】:

作为一种解决方法,我使用自定义的简单堆栈实现解决了这个问题。

就我而言,这只是一个问题:

  navigateBack() 
    if (currentSlide >= 2) 
      updateIndex(1);
     else if (currentSlide == 1) 
      updateIndex(0);
     else if (currentSlide == -1) 
      updateIndex(prevSlide);
    
  

一叠 2 页(currentSlideprevSlide)对我来说已经足够了。使用数组实现更复杂的堆栈应该不会太难。

我还将它放在一个跟踪当前打开页面的状态对象中。为了捕获返回按钮并阻止它自动弹出路由,我在onWillPop 中返回“false”,然后自己处理所有事情:

WillPopScope(
        // onWillPop: () async 
        //   if (navigatorKey.currentState.canPop()) 
        //     print(ModalRoute.of(navigatorKey.currentContext).settings.name);
        //     navigatorKey.currentState.pop();
        //     return false;
        //   
        //   return true;
        // ,
        onWillPop: () async 
          if (navigatorKey.currentState.canPop()) 

            //use custom state that tracks everything itself instead
            appBarState.navigateBack(); 

            //but also keep using navigator for popping and animation transitions
            navigatorKey.currentState.pop();
          
          return false;
        ,

由于我还有其他在应用程序中导航的方式,例如按钮,因此我也需要在那里使用我的自定义 appBarState.navigateBack() 实现:

 child: GestureDetector(
          onTap: () 
            // Navigator.of(pContext).pop();
            if (appBarState.currentSlide != 0) 
              appBarState.navigateBack(); 
              widget.navigatorKey.currentState.pop();

还实现了一种在我们“向前”移动时更新堆栈的方法。 navigateForwards()。在我调用navigatorKey.currentState.pushNamed("/route")的任何地方调用它

理想情况下,我还可以将 navigatorKey 移动到状态中,这样我就不必重复调用 pop 和自定义 appBarState.navigateBack()

该解决方法/解决方案还让我可以更好地控制我希望导航器的行为方式。由于它也修改了我的全局状态(您的确切状态实现并不重要,但我使用的是getItrxdart 的组合),现在我可以在我想要的任何页面上捕捉我的导航中的任何变化并且随时。

希望我也能帮助别人。保持简单。

【讨论】:

以上是关于Flutter Navigator 路由总是“/”的主要内容,如果未能解决你的问题,请参考以下文章

使用 BLoC 的 Flutter 导航:用于从 Navigator 推送路由的上下文必须是 Navigator 小部件的后代

Flutter Navigator:动态初始路由

Flutter 路由

Flutter 路由我定

12.Flutter教程 — 路由管理与Navigator进阶使用(老油条看了都说好!!!)

Flutter Navigator v2.0 如何弹出子嵌套路由