61

If you create an Scafold there is an option for drawer. If you now create this drawer you get automaticly the menu icon on the leading position of the appbar. But i want an other icon there which opens the drawer. I tried to make an iconbutton myself on the leading position but this button can‘t open the drawer even with „Scafold.of(context).openDrawer()“ it can‘t open it.

Is there any option to replace the icon for the drawer button?

CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Lukas Kirner
  • 3,989
  • 6
  • 23
  • 30
  • Sometimes you need to pay attention to the `BuildContext` that you are passing into the `Scaffold.of(context)` method. If that context is the same context that the Scaffold is being built in, that context won't know about the Scaffold, and hence `Scaffold.of(context)` will return null. You can wrap a widget in a `Builder` widget to build it with an updated context. – John Dengis Oct 02 '18 at 16:23
  • @JohnDengis wrapping an AppBar with Builder doesn't work, unfortunately. – Andriy Trubchanin Aug 20 '20 at 08:47
  • @AndriyTrubchanin I didn't mean wrapping the AppBar but you can wrap the leading as shown in one of the other answers. – John Dengis Aug 20 '20 at 20:33

5 Answers5

174

Use a Key in your Scaffold and show the drawer by calling myKey.currentState.openDrawer(), here is a working code:

enter image description here

import "package:flutter/material.dart";

class Test extends StatefulWidget {
  @override
  _TestState createState() => new _TestState();
}

class _TestState extends State<Test> {
  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _scaffoldKey,
      drawer: new Drawer(),
      appBar: new AppBar(
        leading: new IconButton(
          icon: new Icon(Icons.settings),
          onPressed: () => _scaffoldKey.currentState.openDrawer(),
        ),
      ),
    );
  }
}

Boken
  • 4,825
  • 10
  • 32
  • 42
Shady Aziza
  • 50,824
  • 20
  • 115
  • 113
116

Alternative to the accepted answer which does not require a GlobalKey:

class _TestState extends State<Test> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      drawer: new Drawer(),
      appBar: new AppBar(
        leading: Builder(
        builder: (context) => IconButton(
            icon: new Icon(Icons.settings),
            onPressed: () => Scaffold.of(context).openDrawer(),
          ),
        ),
      ),
    );
  }
}
Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Sebastian Roth
  • 11,344
  • 14
  • 61
  • 110
  • 1
    There is an issue. https://www.reddit.com/r/FlutterDev/comments/7yma7y/how_do_you_open_a_drawer_in_a_scaffold_using_code/ – Suyon Won Jan 20 '19 at 10:33
  • @SuyonWon what is the issue? – Sebastian Roth Jan 20 '19 at 23:03
  • 2
    Sorry you're right, you applied an additional Builder(). I missed. – Suyon Won Jan 21 '19 at 05:48
  • I also wrapped the Icon widget with Padding widget so that it's exactly placed: Padding(child:Icon(Icons.menu),padding:EdgeInsets.all(8.0) – temirbek Mar 05 '19 at 07:48
  • 2
    Best answer. Make your local BuildContext for the win. – Michał Dobi Dobrzański Oct 15 '19 at 10:33
  • I prefer this way, because it doesn't make use of Global key: https://stackoverflow.com/questions/51329065/builder-versus-globalkey – Ivan Joaquim Nov 05 '19 at 15:51
  • Your solution is more practical. – Anas Naguib Feb 21 '20 at 11:41
  • Better because it doesn't use a GlobalKey, should be preferred instead of the most voted one – Alessio Apr 17 '20 at 04:52
  • Thanks for this answer. i was developing an web app and i was having issues with opening the app drawer. this answer really helped.!! – Satyam Goyal Sep 07 '20 at 19:11
  • This helped me understand the underlying issue. In my case, I wanted a button in a `BottomNavigation` to trigger the drawer, so `leading` isn't available. Simple solution: instead of creating the `OutlinedButton` directly, call `Builder(builder: (context)=>OutlinedButton...`. Makes sense: the `Scaffold.of` call needs a context within the scaffold, so adding a builder to _create_ the button does the job. – Andrew E Jan 16 '22 at 09:23
  • Scaffold.of() called with a context that does not contain a Scaffold. – Syed Arsalan Kazmi Feb 06 '23 at 21:45
12

Using GlobalKey:

final GlobalKey<ScaffoldState> _key = GlobalKey(); // Create a key

@override
Widget build(BuildContext context) {
  return Scaffold(
    key: _key, // Assign the key to Scaffold.
    drawer: Drawer(),
    floatingActionButton: FloatingActionButton(
      onPressed: () => _key.currentState!.openDrawer(), // <-- Opens drawer
    ),
  );
}

Using Builder:

@override
Widget build(BuildContext context) {
  return Scaffold(
    drawer: Drawer(),
    floatingActionButton: Builder(builder: (context) {
      return FloatingActionButton(
        onPressed: () => Scaffold.of(context).openDrawer(), // <-- Opens drawer.
      );
    }),
  );
}
Uhelliton
  • 167
  • 1
  • 6
8

you need initialize scaffoldKey after that,

Open drawer and close drawer

 GestureDetector(
          onTap: () {
            if(scaffoldKey.currentState.isDrawerOpen){
              scaffoldKey.currentState.openEndDrawer();
            }else{
              scaffoldKey.currentState.openDrawer();
            }
          },
          child:  LeadingIcon(icon: Icons.menu),//your button
        ),
user9139407
  • 964
  • 1
  • 12
  • 25
0
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue),
      home: Scaffold(
        key: _scaffoldKey,
        appBar: AppBar(
          leading: IconButton(
              onPressed: () {
                _scaffoldKey.currentState!.openDrawer();
              },
              icon: const Icon(Icons.home)),
        ),
        drawer: const Drawer(),
      ),

 - List item

    );
  }
}
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 20 '23 at 17:02