首页 文章

颤振:使用导航器推送到新屏幕时保持BottomNavigationBar

提问于
浏览
3

在iOS中,当我们推送到新的ViewController时,我们有一个UITabBarController永久保留在屏幕的底部 .

在Flutter中,我们有一个底部导航栏的脚手架 . 但是,与iOS不同,当我们 Navigator.push 到一个新的屏幕时,这个bottomNavigationBar消失了 .

在我的应用程序中,我想满足此要求:主屏幕有一个 bottomNavigationBar ,其中有2个项目(a和b)显示屏幕A和B.默认情况下,屏幕A显示 . 在屏幕A内,有一个按钮 . 点击该按钮, Navigator.push 到屏幕C.现在在屏幕C中,我们仍然可以看到 bottomNavigationBar . 点击项目b,我转到屏幕B.现在在屏幕B中,点击 bottomNavigationBar 中的项目a,我返回到屏幕C(不是A,A当前在导航层次结构中的C下面) .

我怎样才能做到这一点?多谢你们 .

编辑:我包括一些图片用于演示:

屏幕A Screen A

点击转到C按钮,按到屏幕C Screen C

点击底部导航栏内的右侧项目,转到屏幕B Screen B

5 回答

  • 0

    您需要使用路径创建MaterialApp,并使BottomNavigationBar成为它的兄弟 . 然后使用您传递给BottomNavigationBar的MaterialApp.navigatorKey进行导航 .

    https://medium.com/@swav.kulinski/flutter-navigating-off-the-charts-e118562a36a5

  • 1

    我认为这样做的#right方式是将BottomNavigationBar包含在Hero中,两种情况都使用相同的标签 . 这样,当页面之间的动画发生时,它们将被排除 .

    这是我可以做的一个简短的例子,但我强烈建议清理它,即使用小部件而不是一个巨大的构建块传递英雄字符串,为BottomNavigationBar制作自己的小部件 .

    请注意,在英雄转换期间,它至少会在我的手机上执行 overflow by 0.0000191 pixels ,但是在发布模式下不应该这么做 .

    import'package:flutter / material.dart';

    void main() => runApp(new MaterialApp(
          home: new Builder(
            builder: (context) => new Scaffold(
                  bottomNavigationBar: new Hero(
                    tag: "bottomNavigationBar",
                    child: new BottomNavigationBar(items: [
                      new BottomNavigationBarItem(icon: new Icon(Icons.home), title: new Text("Home")),
                      new BottomNavigationBarItem(icon: new Icon(Icons.ac_unit), title: new Text("AC Unit"))
                    ]),
                  ),
                  body: new SafeArea(
                    child: new Container(
                      constraints: new BoxConstraints.expand(),
                      color: Colors.green,
                      child: new Column(
                        children: <Widget>[
                          new RaisedButton(
                              child: new Text("Press me"),
                              onPressed: () {
                                Navigator.push(
                                    context,
                                    new MaterialPageRoute(
                                        builder: (context) => new Scaffold(
                                              bottomNavigationBar: new Hero(
                                                tag: "bottomNavigationBar",
                                                child: new BottomNavigationBar(items: [
                                                  new BottomNavigationBarItem(icon: new Icon(Icons.home), title: new Text("Home")),
                                                  new BottomNavigationBarItem(icon: new Icon(Icons.ac_unit), title: new Text("AC Unit"))
                                                ]),
                                              ),
                                              body: new SafeArea(
                                                child: new Container(
                                                  constraints:
                                                      new BoxConstraints.expand(),
                                                  color: Colors.red,
                                                  child: new Column(
                                                    children: <Widget>[
                                                      new RaisedButton(
                                                        onPressed: () =>
                                                            Navigator.pop(context),
                                                        child: new Text("Back"),
                                                      )
                                                    ],
                                                  ),
                                                ),
                                              ),
                                            )));
                              })
                        ],
                      ),
                    ),
                  ),
                ),
          ),
        ));
    

    我不知道 hero 系统如何处理多个英雄等,如果你说想要为导航栏设置动画,这可能效果不太好 .

    还有另一种方法可以让你为底部导航栏设置动画;这实际上是一个已经回答的问题:Flutter: Hero transition + widget animation at the same time?

  • 0

    你实际上可以在一个占位符中放置一个这样的结构

    - AppBar
    - body (dynamic content from placeholder)
    - BottomNavigationBar
    

    然后你会有另一个类作为占位符所以每次你点击BottomNavigationBar它会刷新身体的内容

    我发现的一个例子是https://willowtreeapps.com/ideas/how-to-use-flutter-to-build-an-app-with-bottom-navigation

    而且这里有一个太复杂而且不适合我的小事https://medium.com/@swav.kulinski/flutter-navigating-off-the-charts-e118562a36a5

    这个https://medium.com/coding-with-flutter/flutter-case-study-multiple-navigators-with-bottomnavigationbar-90eb6caa6dbf

  • 4

    tl; dr:使用CupertinoTabBarCupertinoTabScaffold

    问题不在于Flutter,而在于用户体验,就像RémiRousselet所提到的那样 .

    事实证明,Material Design不建议层次结构中的子页面访问底部导航栏 .

    但是,iOS人机界面指南推荐此功能 . 因此,要使用此功能,我必须使用Cupertino小部件而不是Material小部件 . 具体来说,在main中,返回包含 CupertinoTabScaffoldWidgetsApp/MaterialApp . 使用 CupertinoTabBar 实现标签栏,每个屏幕都是 CupertinoTabView .

  • 0

    实现这一目标的另一种方法(虽然不是很好的做法)是将材料应用程序嵌套在脚手架的主体中 . 并处理所有“子导航” .

    因此,您的层次结构将如下所示

    Material App
      - home
         - Scaffold
           - body
             - Material App
                  - Scaffold
                      - AppBar
                      - body
                      ...
             - routes (internal)
           - bottomNavigationBar
      - routes (external)
    

    我试过这个,它完美无缺 . 不幸的是我现在无法发布源代码 .

相关问题