Dart 使用命名的路线抖动持续导航栏?

Dart 使用命名的路线抖动持续导航栏?,dart,flutter,Dart,Flutter,我一直在寻找一个很好的Flitter导航/路由器示例,但我没有找到一个 我想要实现的目标非常简单: 突出显示当前顶级路线的持久底部导航栏 命名路线,以便我可以从应用程序内的任何位置导航到任何路线 Navigator.pop应该始终将我带到我所在的上一个视图 BottomNavigationBar的官方颤振演示实现了1,但后退按钮和路由不起作用。PageView和TabView也有同样的问题。还有许多其他教程通过实现MaterialApp路线实现了2和3,但它们似乎都没有持久的导航栏 是否有任何导

我一直在寻找一个很好的Flitter导航/路由器示例,但我没有找到一个

我想要实现的目标非常简单:

  • 突出显示当前顶级路线的持久底部导航栏
  • 命名路线,以便我可以从应用程序内的任何位置导航到任何路线
  • Navigator.pop应该始终将我带到我所在的上一个视图
  • BottomNavigationBar的官方颤振演示实现了1,但后退按钮和路由不起作用。PageView和TabView也有同样的问题。还有许多其他教程通过实现MaterialApp路线实现了2和3,但它们似乎都没有持久的导航栏


    是否有任何导航系统可以满足所有这些要求的例子?

    您所要求的内容可能会违反规则

    在Android上,后退按钮不会在底部和底部之间导航 导航栏视图

    导航抽屉会给你2和3,但不是1。这取决于什么对你更重要

    您可以尝试使用LocalHistoryRoute。这将达到您想要的效果:

    class MainPage extends StatefulWidget {
      @override
      State createState() {
        return new MainPageState();
      }
    }
    
    class MainPageState extends State<MainPage> {
      int _currentIndex = 0;
      List<int> _history = [0];
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text('Bottom Nav Back'),
          ),
          body: new Center(
            child: new Text('Page $_currentIndex'),
          ),
          bottomNavigationBar: new BottomNavigationBar(
            currentIndex: _currentIndex,
            items: <BottomNavigationBarItem>[
              new BottomNavigationBarItem(
                icon: new Icon(Icons.touch_app),
                title: new Text('keypad'),
              ),
              new BottomNavigationBarItem(
                icon: new Icon(Icons.assessment),
                title: new Text('chart'),
              ),
              new BottomNavigationBarItem(
                icon: new Icon(Icons.cloud),
                title: new Text('weather'),
              ),
            ],
            onTap: (int index) {
              _history.add(index);
              setState(() => _currentIndex = index);
              Navigator.push(context, new BottomNavigationRoute()).then((x) {
                _history.removeLast();
                setState(() => _currentIndex = _history.last);
              });
            },
          ),
        );
      }
    }
    
    class BottomNavigationRoute extends LocalHistoryRoute<void> {}
    
    class主页扩展StatefulWidget{
    @凌驾
    状态createState(){
    返回新的MainPageState();
    }
    }
    类MainPageState扩展状态{
    int _currentIndex=0;
    列表_历史=[0];
    @凌驾
    小部件构建(构建上下文){
    归还新脚手架(
    appBar:新的appBar(
    标题:新文本(“底部导航背面”),
    ),
    正文:新中心(
    子项:新文本('Page$\u currentIndex'),
    ),
    bottomNavigationBar:新的bottomNavigationBar(
    currentIndex:_currentIndex,
    项目:[
    新海底导航气压计(
    图标:新图标(Icons.touch_应用程序),
    标题:新文本(“键盘”),
    ),
    新海底导航气压计(
    图标:新图标(图标。评估),
    标题:新文本(“图表”),
    ),
    新海底导航气压计(
    图标:新图标(Icons.cloud),
    标题:新文本(“天气”),
    ),
    ],
    onTap:(int索引){
    _添加(索引);
    设置状态(()=>_currentIndex=index);
    push(上下文,new BottomNavigationRoute())。然后((x){
    _removeLast();
    setState(()=>\u currentIndex=\u history.last);
    });
    },
    ),
    );
    }
    }
    类BottomNavigationRoute扩展LocalHistoryRoute{}
    
    与您描述的行为完全相同,但采用iOS风格。但也可能是这样


    您的所有3项要求都可以通过使用自定义

    Flitter团队对此进行了深入研究,他们的文章如下:

    基本上,您需要在自定义的
    导航器中包装脚手架主体:

    class\u MainScreenState扩展状态{
    最终_navigatorKey=GlobalKey();
    // ...
    @凌驾
    小部件构建(构建上下文){
    返回脚手架(
    正文:导航器(
    键:_导航工作,
    initialRoute:“/”,
    onGenerateRoute:(路由设置){
    WidgetBuilder;
    //在此处管理您的路线名称
    开关(设置.名称){
    案例“/”:
    builder=(BuildContext上下文)=>HomePage();
    打破
    案例“/page1”:
    生成器=(BuildContext上下文)=>Page1();
    打破
    案例“/page2”:
    生成器=(BuildContext上下文)=>Page2();
    打破
    违约:
    抛出异常('无效路由:${settings.name}');
    }
    //您还可以返回PageRouteBuilder和
    //定义页面之间的自定义转换
    返回物料路线(
    建筑商:建筑商,
    设置:设置,
    );
    },
    ),
    bottomNavigationBar:\u您的bottomNavigationBar,
    );
    }
    }
    
    在底部导航栏中,要导航到新自定义
    导航器中的新屏幕,只需调用以下命令:

    \u navigatorKey.currentState.pushNamed('/yourRouteName');
    
    要实现第三个要求,即
    Navigator.pop
    将您带到上一个视图,您需要使用
    WillPopScope
    包装自定义
    Navigator

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: WillPopScope(
          onWillPop: () async {
            if (_navigatorKey.currentState.canPop()) {
              _navigatorKey.currentState.pop();
              return false;
            }
            return true;
          },
          child: Navigator(
            // ...
          ),
        ),
        bottomNavigationBar: _yourBottomNavigationBar,
      );
    }
    

    就这样!无需手动处理pop或管理自定义历史记录列表。

    这是我想要实现的目标,即使它违反了一些任意的设计规则。即使是官方的Youtube应用程序在按下后退按钮时也会在底部导航栏视图之间导航。Spotify和几乎所有的大型应用程序也是如此。每次点击都会推一个导航堆栈,但从未删除。根据问题的要求,它们会被Android的后退按钮删除。我通过扩展
    Route
    而不是安卓上的
    LocalHistoryRoute
    来实现,在包含底部导航栏的活动中点击后退按钮应弹出到第一个索引(第一页)&再次点击后退按钮应完成该活动。您找到问题的解决方案了吗?@Daniel.V不,我没有。我最终使用BottomNavigationBar实现了1,放弃了第2个需求,并手动处理pop,这样我就可以始终导航回当前选项卡的根视图。从那时起,开源场景已经发展,因此可能会有新的库至少可以实现1和2。如何保持每个选项卡的活力。在上面的方法中,当移动到下一个选项卡/bottomNavigationItem时,将重新创建每个页面。@AbdullahKhan您不需要这样做。只需将状态与UI分开。一些有用的库选项:Redux、BLoC、MobX。@czx如何在子路由中隐藏底部导航栏?是否有一种方法可以从最高层使用它?我使用flatterforweb,这种导航在url选项卡上无法工作。