How to use BottomNavigationBar with Navigator?

后端 未结 6 778
北荒
北荒 2020-12-02 08:36

The Flutter Gallery example of BottomNavigationBar uses a Stack of FadeTransitions in the body of the Scaffold.

I

相关标签:
6条回答
  • 2020-12-02 08:52

    The Complete Example

    First make a class MyBottomBarDemo

    class MyBottomBarDemo extends StatefulWidget {
      @override
      _MyBottomBarDemoState createState() => new _MyBottomBarDemoState();
    }
    
    class _MyBottomBarDemoState extends State<MyBottomBarDemo> {
      int _pageIndex = 0;
      PageController _pageController;
    
      List<Widget> tabPages = [
        Screen1(),
        Screen2(),
        Screen3(),
      ];
    
      @override
      void initState(){
        super.initState();
        _pageController = PageController(initialPage: _pageIndex);
      }
    
      @override
      void dispose() {
        _pageController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("BottomNavigationBar", style: TextStyle(color: Colors.white)),
            backgroundColor: Colors.deepPurple,
          ),
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: _pageIndex,
            onTap: onTabTapped,
            backgroundColor: Colors.white,
            items: <BottomNavigationBarItem>[
              BottomNavigationBarItem( icon: Icon(Icons.home), title: Text("Home")),
              BottomNavigationBarItem(icon: Icon(Icons.mail), title: Text("Messages")),
              BottomNavigationBarItem(icon: Icon(Icons.person), title: Text("Profile")),
            ],
    
          ),
          body: PageView(
            children: tabPages,
            onPageChanged: onPageChanged,
            controller: _pageController,
          ),
        );
      }
      void onPageChanged(int page) {
        setState(() {
          this._pageIndex = page;
        });
      }
    
      void onTabTapped(int index) {
        this._pageController.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
      }
    }
    

    Then create a your screens

    class Screen1 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
            color: Colors.green,
                child: Center(child: Text("Screen 1")),
        );
      }
    }
    
    class Screen2 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.yellow,
          child: Center(child: Text("Screen 2")),
        );
      }
    }
    
    class Screen3 extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Container(
          color: Colors.cyan,
          child: Center(child: Text("Screen 3")),
        );
      }
    }
    

    0 讨论(0)
  • 2020-12-02 08:55

    Here is an example how you can use Navigator with BottomNavigationBar to navigate different screen.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      // This navigator state will be used to navigate different pages
      final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
      int _currentTabIndex = 0;
    
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            body: Navigator(key: _navigatorKey, onGenerateRoute: generateRoute),
            bottomNavigationBar: _bottomNavigationBar(),
          ),
        );
      }
    
      Widget _bottomNavigationBar() {
        return BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              title: Text("Home"),
            ),
            BottomNavigationBarItem(
                icon: Icon(Icons.account_circle), title: Text("Account")),
            BottomNavigationBarItem(
              icon: Icon(Icons.settings),
              title: Text("Settings"),
            )
          ],
          onTap: _onTap,
          currentIndex: _currentTabIndex,
        );
      }
    
      _onTap(int tabIndex) {
        switch (tabIndex) {
          case 0:
            _navigatorKey.currentState.pushReplacementNamed("Home");
            break;
          case 1:
            _navigatorKey.currentState.pushReplacementNamed("Account");
            break;
          case 2:
            _navigatorKey.currentState.pushReplacementNamed("Settings");
            break;
        }
        setState(() {
          _currentTabIndex = tabIndex;
        });
      }
    
      Route<dynamic> generateRoute(RouteSettings settings) {
        switch (settings.name) {
          case "Account":
            return MaterialPageRoute(builder: (context) => Container(color: Colors.blue,child: Center(child: Text("Account"))));
          case "Settings":
            return MaterialPageRoute(builder: (context) => Container(color: Colors.green,child: Center(child: Text("Settings"))));
          default:
            return MaterialPageRoute(builder: (context) => Container(color: Colors.white,child: Center(child: Text("Home"))));
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-02 08:56
    int index = 0;
    
    @override
    Widget build(BuildContext context) {
      return new Scaffold(
        body: new Stack(
          children: <Widget>[
            new Offstage(
              offstage: index != 0,
              child: new TickerMode(
                enabled: index == 0,
                child: new MaterialApp(home: new YourLeftPage()),
              ),
            ),
            new Offstage(
              offstage: index != 1,
              child: new TickerMode(
                enabled: index == 1,
                child: new MaterialApp(home: new YourRightPage()),
              ),
            ),
          ],
        ),
        bottomNavigationBar: new BottomNavigationBar(
          currentIndex: index,
          onTap: (int index) { setState((){ this.index = index; }); },
          items: <BottomNavigationBarItem>[
            new BottomNavigationBarItem(
              icon: new Icon(Icons.home),
              title: new Text("Left"),
            ),
            new BottomNavigationBarItem(
              icon: new Icon(Icons.search),
              title: new Text("Right"),
            ),
          ],
        ),
      );
    }
    

    You should keep each page by Stack to keep their state. Offstage stops painting, TickerMode stops animation. MaterialApp includes Navigator.

    0 讨论(0)
  • 2020-12-02 09:00

    Here is example:

      int _currentIndex = 0;
    
    
      Route<Null> _getRoute(RouteSettings settings) {
        final initialSettings = new RouteSettings(
            name: settings.name,
            isInitialRoute: true);
    
        return new MaterialPageRoute<Null>(
            settings: initialSettings,
            builder: (context) =>
            new Scaffold(
              body: new Center(
                  child: new Container(
                      height: 200.0,
                      width: 200.0,
                      child: new Column(children: <Widget>[
                        new Text(settings.name),
                        new FlatButton(onPressed: () =>
                            Navigator.of(context).pushNamed(
                                "${settings.name}/next"), child: new Text("push")),
                      ],
                      ))
              ),
              bottomNavigationBar: new BottomNavigationBar(
                  currentIndex: _currentIndex,
                  onTap: (value) {
                    final routes = ["/list", "/map"];
                    _currentIndex = value;
                    Navigator.of(context).pushNamedAndRemoveUntil(
                        routes[value], (route) => false);
                  },
                  items: [
                    new BottomNavigationBarItem(
                        icon: new Icon(Icons.list), title: new Text("List")),
                    new BottomNavigationBarItem(
                        icon: new Icon(Icons.map), title: new Text("Map")),
                  ]),
            ));
      }
    
      @override
      Widget build(BuildContext context) =>
          new MaterialApp(
            initialRoute: "/list",
            onGenerateRoute: _getRoute,
            theme: new ThemeData(
              primarySwatch: Colors.blue,
            ),
          );
    

    You can set isInitialRoute to true and pass it to MaterialPageRoute. It will remove pop animation.

    And to remove old routes you can use pushNamedAndRemoveUntil

    Navigator.of(context).pushNamedAndRemoveUntil(routes[value], (route) => false);
    

    To set current page you can have a variable in your state _currentIndex and assign it to BottomNavigationBar:

    0 讨论(0)
  • 2020-12-02 09:02
    Navigator.of(context).pushNamedAndRemoveUntil(
                    routes[value], (route) => true);
    

    I had to use true to enable back button.

    NB: I was using Navigator.pushNamed() for navigation.

    0 讨论(0)
  • 2020-12-02 09:03

    Output:

    Code:

    int _index = 0;
    
    @override
    Widget build(BuildContext context) {
      Widget child;
      switch (_index) {
        case 0:
          child = FlutterLogo();
          break;
        case 1:
          child = FlutterLogo(colors: Colors.orange);
          break;
        case 2:
          child = FlutterLogo(colors: Colors.red);
          break;
      }
    
      return Scaffold(
        body: SizedBox.expand(child: child),
        bottomNavigationBar: BottomNavigationBar(
          onTap: (newIndex) => setState(() => _index = newIndex),
          currentIndex: _index,
          items: [
            BottomNavigationBarItem(icon: Icon(Icons.looks_one), title: Text("Blue")),
            BottomNavigationBarItem(icon: Icon(Icons.looks_two), title: Text("Orange")),
            BottomNavigationBarItem(icon: Icon(Icons.looks_3), title: Text("Red")),
          ],
        ),
      );
    }
    
    0 讨论(0)
提交回复
热议问题