Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically open a Drawer by tapping on a BottomNavigationBarItem?

Tags:

flutter

dart

I'm making a flutter app and I need to be able to open the Drawer by tapping on a BottomNavigationBarItem. Is there any way to do that?

The UX designer guy put the drawer menu icon at index 0 in the bottom navigation bar. I tried to find an answer in the Flutter documentation but I didn't find anything relevant. I actually found a way of opening it programmatically (as you can see below) but it does not work like that in my case.

class _HomeState extends State<Home> {
  int _currentIndex = 1; // 0 = menu

  final List<Widget> _children = [
    PlaceholderWidget(Colors.deepPurple),
    PlaceholderWidget(Colors.white),
    DiagnosisWidget(),
    FindUsWidget(),
  ];

  _navItem(String text, IconData icon) {
    return BottomNavigationBarItem(
      /* Building Bottom nav item */
    );
  }

  void onTabTapped(int index) {
    setState(() {
      if(index == 0) {
        Scaffold.of(context).openDrawer(); // This is what I've tried
      }
      else {
        _currentIndex = index;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      drawer: Drawer(
        child: MyDrawer(),
      ),
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed, // 4+ items in the bar
        items: [
          _navItem('MENU', Icons.menu),
          _navItem('HOME', Icons.home),
          _navItem('DIAGNOSIS', Icons.person),
          _navItem('FIND US', Icons.location_on),
        ],
      ),
    );
  }
}

Instead of having the Drawer showing up, I get the following error message :

Scaffold.of() called with a context that does not contain a Scaffold.

like image 275
Mickaël D Avatar asked May 06 '19 14:05

Mickaël D


1 Answers

It's because in onTabTapped you use a context that doesn't contain the Scaffold you create.

You instantiate the Scaffold in build but in onTabTapped you're looking for a parent Scaffold in the current context (_HomeState context).

You can use Builder inside the Scaffold to get the correct context or use a GlobalKey on your Scaffold.

See this answer for more details.

EDIT: In your case a GlobalKey is mush easier to implement.

You can do the following :

class _HomeState extends State<Home> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); // ADD THIS LINE
  int _currentIndex = 1; // 0 = menu

  final List<Widget> _children = [
    PlaceholderWidget(Colors.deepPurple),
    PlaceholderWidget(Colors.white),
    DiagnosisWidget(),
    FindUsWidget(),
  ];

  _navItem(String text, IconData icon) {
    return BottomNavigationBarItem(
      /* Building Bottom nav item */
    );
  }

  void onTabTapped(int index) {
    setState(() {
      if(index == 0) {
        _scaffoldKey.currentState.openDrawer(); // CHANGE THIS LINE
      }
      else {
        _currentIndex = index;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey, // ADD THIS LINE
      drawer: Drawer(
        child: MyDrawer(),
      ),
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        type: BottomNavigationBarType.fixed, // 4+ items in the bar
        items: [
          _navItem('MENU', Icons.menu),
          _navItem('HOME', Icons.home),
          _navItem('DIAGNOSIS', Icons.person),
          _navItem('FIND US', Icons.location_on),
        ],
      ),
    );
  }
}
like image 157
Tristan Pct Avatar answered Nov 16 '22 08:11

Tristan Pct