Flutter persistent navigation bar with named routes?

前端 未结 3 1171
渐次进展
渐次进展 2020-12-05 03:02

I\'ve been searching around for a good navigation/router example for Flutter but I have not managed to find one.

What I want to achieve is very simple:

相关标签:
3条回答
  • 2020-12-05 03:31

    All of your 3 requirements can be achieved by using a custom Navigator.

    The Flutter team did a video on this, and the article they followed is here: https://medium.com/flutter/getting-to-the-bottom-of-navigation-in-flutter-b3e440b9386

    Basically, you will need to wrap the body of your Scaffold in a custom Navigator:

    class _MainScreenState extends State<MainScreen> {
      final _navigatorKey = GlobalKey<NavigatorState>();
    
      // ...
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Navigator(
            key: _navigatorKey,
            initialRoute: '/',
            onGenerateRoute: (RouteSettings settings) {
              WidgetBuilder builder;
              // Manage your route names here
              switch (settings.name) {
                case '/':
                  builder = (BuildContext context) => HomePage();
                  break;
                case '/page1':
                  builder = (BuildContext context) => Page1();
                  break;
                case '/page2':
                  builder = (BuildContext context) => Page2();
                  break;
                default:
                  throw Exception('Invalid route: ${settings.name}');
              }
              // You can also return a PageRouteBuilder and
              // define custom transitions between pages
              return MaterialPageRoute(
                builder: builder,
                settings: settings,
              );
            },
          ),
          bottomNavigationBar: _yourBottomNavigationBar,
        );
      }
    }
    

    Within your bottom navigation bar, to navigate to a new screen in the new custom Navigator, you just have to call this:

    _navigatorKey.currentState.pushNamed('/yourRouteName');
    

    To achieve the 3rd requirement, which is Navigator.pop taking you to the previous view, you will need to wrap the custom Navigator with a WillPopScope:

    @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,
      );
    }
    

    And that should be it! No need to manually handle pop or manage a custom history list.

    0 讨论(0)
  • 2020-12-05 03:32

    CupertinoTabBar behave exactly same as you described, but in iOS style. It can be used in MaterialApps however.

    Sample Code

    0 讨论(0)
  • 2020-12-05 03:41

    What you are asking for would violate the material design specification.

    On Android, the Back button does not navigate between bottom navigation bar views.

    A navigation drawer would give you 2 and 3, but not 1. It depends on what's more important to you.

    You could try using LocalHistoryRoute. This achieves the effect you want:

    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> {}
    
    0 讨论(0)
提交回复
热议问题