Keep the Bottom Navigation Bar Static when Pushed

2020-06-09 11:45发布

问题:

I am a beginner with flutter and dart. I have been trying to implement a navigationBar on three different pages in my app. The toggling works well for an individual page but I have problems persisting the active and inactive tabs state on all the pages. It seems like when it navigates to another page, I lose the active state too the tabs. This is my code.

AppFooter.dart

import 'package:flutter/material.dart';

class AppFooter extends StatefulWidget {
  @override
  _AppFooterState createState() => _AppFooterState();
}

class _AppFooterState extends State<AppFooter> {
  int index = 0;
  @override
  Widget build(BuildContext context) {
    return new Theme(
      data: Theme.of(context).copyWith(
          // sets the background color of the `BottomNavigationBar`
          canvasColor: Colors.white,
          // sets the active color of the `BottomNavigationBar` if `Brightness` is light
          primaryColor: Colors.green,
          textTheme: Theme.of(context)
              .textTheme
              .copyWith(caption: new TextStyle(color: Colors.grey))),
      child: new BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          currentIndex: index,
          onTap: (int index) {
            setState(() {
              this.index = index;
            });
          switch (index){
            case 0:  Navigator.of(context).pushNamed('/dashboard');
            break;
            case 1:  Navigator.of(context).pushNamed('/medical centre');
            break;
            case 2:  Navigator.of(context).pushNamed('/history');
            break;

          }

          },
          items: [
            new BottomNavigationBarItem(
                backgroundColor: Colors.white,
                icon: index==0?new Image.asset('assets/images/dashboard_active.png'):new Image.asset('assets/images/dashboard_inactive.png'),
                title: new Text('Dashboard', style: new TextStyle(fontSize: 12.0))),
           new BottomNavigationBarItem(
               backgroundColor: Colors.white,
               icon: index==1?new Image.asset('assets/images/medical_sevice_active.png'):new Image.asset('assets/images/medical_sevice_inactive.png'),
               title: new Text('Health Services', style: new TextStyle(fontSize: 12.0))),
            new BottomNavigationBarItem(
                icon: InkWell(
                  child: Icon(
                    Icons.format_align_left,
                   // color: green,
                    size: 20.0,
                  ),
                ),
                title: new Text('History', style: new TextStyle(fontSize: 12.0))),
          ]),
    );
  }
}

回答1:

If I understand your question correctly, you need the bottom navigation bar persisted on all three pages. There is a well-written article on how to achieve it. You can find the details here.

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

https://github.com/bizz84/nested-navigation-demo-flutter

All credits go to the original author.



回答2:

Use PageView and bottomNavigationBar :

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
  static const String _title = 'Flutter App';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: App(),
    );
  }
}

class App extends StatefulWidget {
  App({Key key}) : super(key: key);
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  PageController _myPage;
  var selectedPage;

  @override
  void initState() {
    super.initState();
    _myPage = PageController(initialPage: 1);
    selectedPage = 1;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: PageView(
          physics: NeverScrollableScrollPhysics(),
          controller: _myPage,
          children: <Widget>[
            Center(
              child: Text("Another Page"),
            ),
            Center(
                child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text("Page 1"),
                RaisedButton(
                  onPressed: () {
                    _myPage.jumpToPage(0);
                    setState(() {
                      selectedPage = 0;
                    });
                  },
                  child: Text("Go to another page"),
                )
              ],
            )),
            Center(child: Text("Page 2")),
            Center(child: Text("Page 3")),
          ],
        ),
        bottomNavigationBar: BottomAppBar(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              IconButton(
                icon: Icon(Icons.home),
                color: selectedPage == 1 ? Colors.blue : Colors.grey,
                onPressed: () {
                  _myPage.jumpToPage(1);
                  setState(() {
                    selectedPage = 1;
                  });
                },
              ),
              IconButton(
                icon: Icon(Icons.star),
                color: selectedPage == 2 ? Colors.blue : Colors.grey,
                onPressed: () {
                  _myPage.jumpToPage(2);
                  setState(() {
                    selectedPage = 2;
                  });
                },
              ),
              IconButton(
                icon: Icon(
                  Icons.settings,
                ),
                color: selectedPage == 3 ? Colors.blue : Colors.grey,
                onPressed: () {
                  _myPage.jumpToPage(3);
                  setState(() {
                    selectedPage = 3;
                  });
                },
              ),
            ],
          ),
        ));
  }
}

Hope it helps.



回答3:

I created a small, super easy to use package that let you do that effect CustomNavigator. And wrote a tutorial about it on Medium you can find it here.

So it goes like this

// Here's the custom scaffold widget
// It takes a normal scaffold with mandatory bottom navigation bar
// and children who are your pages
CustomScaffold(
  scaffold: Scaffold(
    bottomNavigationBar: BottomNavigationBar(
      items: _items,
    ),
  ),

  // Children are the pages that will be shown by every click
  // They should placed in order such as
  // `page 0` will be presented when `item 0` in the [BottomNavigationBar] clicked.
  children: <Widget>[
    Page('0'),
    Page('1'),
    Page('2'),
  ],

  // Called when one of the [items] is tapped.
  onItemTap: (index) {},
);

The cool thing about this library that it works efficiently. It creates a nested navigator (which is very unpleasant to do) and uses it for navigation in your widget tree. And of course you can always use the default navigator from MaterialApp



回答4:

I am working on a beta version of an express_app plugin, which achieve the required result.

Two days ago, I implemented an addition where you can set an ExpressHome and it can be any part of your tree, in addition to setting your routes of course. When changing the routes, everything under ExpressHome will change only and the rest will stay the same (i.e. you can have a permanent bar easily.

I will publish a more-recent version this evening, and if you would like a specific demo about your use case, let me know.



回答5:

Navigator.of(context).pushNamed(); is for Navigation with page transition. So, in this situation, the method is not match.

You can use BottomNavigationBar with Scaffold.

example code:


class AppFooter extends StatefulWidget {
  @override
  _AppFooterState createState() => _AppFooterState();
}

class _AppFooterState extends State<AppFooter> {
  int _currentIndex = 0;

  List<Widget> _pages = [
    Text("page1"),
    Text("page2"),
    Text("page3"),
  ];


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.fixed,
        currentIndex: _currentIndex,
        onTap: (int index) {
          setState(() {
            _currentIndex = index;
          });
        },
        items: [
          new BottomNavigationBarItem(
              backgroundColor: Colors.white,
              icon: _currentIndex == 0
                  ? new Image.asset('assets/images/dashboard_active.png')
                  : new Image.asset('assets/images/dashboard_inactive.png'),
              title:
                  new Text('Dashboard', style: new TextStyle(fontSize: 12.0))),
          new BottomNavigationBarItem(
              backgroundColor: Colors.white,
              icon: _currentIndex == 1
                  ? new Image.asset('assets/images/medical_sevice_active.png')
                  : new Image.asset(
                      'assets/images/medical_sevice_inactive.png'),
              title: new Text('Health Services',
                  style: new TextStyle(fontSize: 12.0))),
          new BottomNavigationBarItem(
              icon: InkWell(
                child: Icon(
                  Icons.format_align_left,
                  // color: green,
                  size: 20.0,
                ),
              ),
              title: new Text('History', style: new TextStyle(fontSize: 12.0))),
        ],
      ),
    );
  }
}



标签: dart flutter