Flutter update BottomNavigationBar

2020-06-05 01:48发布

问题:

I am using a BottomNavigationBar together with a TabController. By clicking on the different Tabs of the BottomNavigationBar the TabView is changing the content. However if I swipe on the TabView to switch to another view/tab the BottomNavigationBar is not updating to the tab I swiped to. I already have added a listener to the TabController to detect changes. But how can I update BottomNavigationBar programmatically to reflect the change?

回答1:

I think it is way more elegant to use PageView instead of TabBarView specially in your case.

class BottomBarExample extends StatefulWidget {
  @override
  _BottomBarExampleState createState() => new _BottomBarExampleState();
}

class _BottomBarExampleState extends State<BottomBarExample> {
  int _page = 0;
  PageController _c;
  @override
  void initState(){
    _c =  new PageController(
      initialPage: _page,
    );
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      bottomNavigationBar: new BottomNavigationBar(
        currentIndex: _page,
        onTap: (index){
          this._c.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
        },
        items: <BottomNavigationBarItem>[
        new BottomNavigationBarItem(icon: new Icon(Icons.supervised_user_circle), title: new Text("Users")),
        new BottomNavigationBarItem(icon: new Icon(Icons.notifications), title: new Text("Alerts")),
        new BottomNavigationBarItem(icon: new Icon(Icons.email), title: new Text("Inbox")),

      ],

      ),
      body: new PageView(
        controller: _c,
        onPageChanged: (newPage){
          setState((){
            this._page=newPage;
          });
        },
        children: <Widget>[
          new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Icon(Icons.supervised_user_circle),
                new Text("Users")
              ],
            ),
          ),
          new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Icon(Icons.notifications),
                new Text("Alerts")
              ],
            ),
          ),
          new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Icon(Icons.mail),
                new Text("Inbox")
              ],
            ),
          ),
        ],
      ),
    );
  }
}


回答2:

you should update the current index of bottomNavigationBar to match the new index of tabview when you swipe on the TabView

class _TabBarWithBottomNavBarState extends State<TabBarWithBottomNavBar> with SingleTickerProviderStateMixin {
  int _bottomNavBarIndex = 0;
  TabController _tabController;
  void _tabControllerListener(){
    setState(() {
      _bottomNavBarIndex = _tabController.index;
    });
  }


 @override
  void initState() {
    _tabController = TabController(length: 3, vsync: this);
    _tabController.addListener(_tabControllerListener);
    super.initState();
  }

  @override
  void dispose() {
    _tabController.dispose();
    _tabController.removeListener(_tabControllerListener);
    super.dispose();
  }


回答3:

For who is looking for a short solution here is mine, maybe it will be useful for someone:

    class App extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => AppState();
}

class AppState extends State<App> {

  int currentTab = 0;

  void _selectTab(int index) {
    debugPrint (" index = $index ");
    setState(() {
      currentTab = index;
    });

    switch (currentTab) {
    case 0:

      debugPrint (" my index 0 ");
      break;

      case 1:
       debugPrint (" my index 1 ");
      break;

      case 2:
       debugPrint (" my index 2 ");
      break;

  }

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _buildBody(),
      bottomNavigationBar: BottomNavigationBar(
       currentIndex: currentTab,
       onTap: _selectTab,

      items: [
        BottomNavigationBarItem(
          icon: Icon(Icons.home), title: Text("Home"),
        ),

        BottomNavigationBarItem(
          icon: Icon(Icons.message), title: Text("Message"),
        ),

        BottomNavigationBarItem(
          icon: Icon(Icons.settings), title: Text("Settings"),
        ),

      ],

      ),
    );
  }

  Widget _buildBody() {
    // return a widget representing a page
  }
}

And we dont forget the main, should be like this:

import 'package:flutter/material.dart';
import 'App.dart';

void main() {
  runApp( MaterialApp(
        home: App(),
  )
    );
}