Search code examples
flutterdartbottomnavigationview

Nested BottomNavigationBar results in Duplicate appBar


I've got a nested BottomNavigationBar which allows me to create a stack within each item. This allows me to pop back to the original page within a stack. But after pushing to another page the appBar is duplicated. If I remove the original appBar, I am left without an appBar on the landing page. If I remove the destination appBar I lose the arrow to pop back.

So I'm thinking I should either try to;

  • Programmatically remove the first appBar when pushing to the destination page,
  • Remove the destination appBar and somehow get the original appBar to inherit the behaviour of the destination appBar.

Are either of these approaches sensible? If so what's the best way to do it? Or should I adopt an entirely different approach? Is there a way to have both a permanent BottomnavigationBar and appBar?

Here's the main code which houses the nested BottomNavigationBar;

class TabsScreen extends StatefulWidget {
  @override
  _TabsScreenState createState() => _TabsScreenState();
}

class _TabsScreenState extends State<TabsScreen> {
  int _currentIndex = 0;
  final _home = GlobalKey<NavigatorState>();
  final _messages = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
     return Scaffold(
       appBar: AppBar(
      //some stuff
       ),
      body: IndexedStack(
        index: _currentIndex,
        children: <Widget>[
          Navigator(
            key: _home,
            onGenerateRoute: (route) => MaterialPageRoute(
              settings: route,
              builder: (context) => MainPage(),
            ),
          ),
          Navigator(
            key: _messages,
            onGenerateRoute: (route) => MaterialPageRoute(
              settings: route,
              builder: (context) => Messages(),
            ),
          ),     
          ),     
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: _currentIndex,
        onTap: (val) => _onTap(val, context),
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Home'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.message),
            title: Text('Messages'),
          ),          
        ],
      ),
    );
  }

  void _onTap(int val, BuildContext context) {
    if (_currentIndex == val) {
      switch (val) {
        case 0:
          _home.currentState.popUntil((route) => route.isFirst);
          break;
        case 1:
          _messages.currentState.popUntil((route) => route.isFirst);
          break;        
        default:
      }
    } else {
      if (mounted) {
        setState(() {
          _currentIndex = val;
        });
      }
    }
  }
}

Here's the code which pushes to the destination page;

  onSwipeUp: () {
              Navigator.push(
              context,
              PageTransition(
                type: PageTransitionType.downToUp,
                child: HomeReply(),
              )
          );
        },

And here's the destination code:

class HomeReply extends StatefulWidget {
  @override
  _HomeReplyState createState() => new _HomeReplyState();
}

class _HomeReplyState extends State<HomeReply> {

  @override
  void initState(){}

  @override
  Widget build(BuildContext context) {
    return
           Scaffold(
                appBar: AppBar(
                    title: Text(
                      "Back to " + "'" + originalTitle + "'",
                    ),
                  ),
                body: ReplyStage(),          
       );
  }
}

Solution

  • I ended up using an entirely different approach using Flutters Nested Navigators plugin;

    https://github.com/n0vah/nested_navigators