How to use Drawer without Scaffold.drawer?

You can use Drawer, but you must supply a DrawerController, and also arrange for the drawer to overlay your other content. This is easy to do with a Stack. Its important that the stack hold a non-transparent container, otherwise you'll get rendering artifacts when the draw slides in and out. Scaffold doesn't require this, however, annoyingly, it also rebuild the other content as the draw moves (exactly the type of thing they've tried to avoid).

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutterui/util/layout_util.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) =>
      MaterialApp(title: 'Flutter Playground',
          home: Material(child:DrawerStack(body: body(), drawer: _drawer())));
}

Drawer _drawer() =>Drawer(
  child: SafeArea(
    child: Center(
      child: Column(
        children: [
          Text('endDrawer content'),
          Builder(builder:(context) => RaisedButton(
            child: Text('Click', semanticsLabel: 'Click 2'),
            onPressed: () {
              Navigator.pop(context);
            },
          )),
        ],
      ),
    ),
  ),
);

Widget body() => Container(
  decoration: BoxDecoration(color: Color.fromARGB(255, 255, 255, 255)),
        child: SafeArea(
            child: Center(
                child: Column(children: [
      Text('Body'), // style:TextStyle(fontSize: 14.0,color: Colors.black)),
      Builder(builder:(context) => RaisedButton(
          child: Text('Open drawer'),
          onPressed: () {
            (context.ancestorWidgetOfExactType(DrawerStack) as DrawerStack).openDrawer();
//            DrawerStack.of(context).openDrawer();
          })),
    ]))));


class DrawerStack extends StatelessWidget {
  final GlobalKey<DrawerControllerState> _drawerKey =
  GlobalKey<DrawerControllerState>();
  final drawerScrimColor = Color.fromARGB(90, 100, 100, 128);
  final double drawerEdgeDragWidth = null;
  final DragStartBehavior drawerDragStartBehavior = DragStartBehavior.start;

  final Widget body;
  final Drawer drawer;

  DrawerStack({Key key, this.body, this.drawer}) : super(key: key);

  void openDrawer() {
    _drawerKey.currentState?.open();
  }

  @override
  Widget build(BuildContext context) => Stack(
    children: [
      // body
      body,

      DrawerController(
        key: _drawerKey,
        alignment: DrawerAlignment.end,
        child: drawer,
        drawerCallback: (_){},
        dragStartBehavior: drawerDragStartBehavior,
        //widget.drawerDragStartBehavior,
        scrimColor: drawerScrimColor,
        edgeDragWidth: drawerEdgeDragWidth,
      ),
    ],
  );
}


It works perfectly for me. Here is a working example with a dedicated "Show Drawer" button in the bottom bar (the drawer can also be dragged in from the left):

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Playground',
      home: TestPage(),
    );
  }
}

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Body'),
      ),
      bottomNavigationBar: Builder(builder: (BuildContext context) {
        return BottomAppBar(
          color: Colors.orange,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              IconButton(icon: Icon(Icons.menu), onPressed: () {
                Scaffold.of(context).openDrawer();;
              }),
              IconButton(icon: Icon(Icons.message), onPressed: () {}),
            ],
          ),
        );
        },),
      drawer: Drawer(
        child: SafeArea(
          right: false,
          child: Center(
            child: Text('Drawer content'),
          ),
        ),
      ),
    );
  }
}

Flutter version: Latest master build (though I'm also quite sure that it works with the beta version)


You can openDrawer of global key from the flutter itself to do the job.

  1. Scaffold.of(context).openDrawer() / Scaffold.of(context).openEndDrawer();
  2. scaffoldKey.currentState.openDrawer(); / scaffoldKey.currentState..openEndDrawer();

Case 1

bottomNavigationBar:BottomAppBar(
      elevation: 10,
      shape: CircularNotchedRectangle(),
      child: Container(
        height: 80,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            Expanded(
              child: GestureDetector(
                onTap: () {
                  Scaffold.of(context).openDrawer();
                },
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(Icons.dashboard),
                    Text(
                      'DASHBOARD',
                      style: TextStyle(color: Colors.black),
                    ),
                  ],
                ),
              ),
            ),
            Expanded(
              child: GestureDetector(
                onTap: () {},
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(Icons.home),
                    Text(
                      'CHALLENGES',
                      style: TextStyle(color: Colors.black),
                    ),
                  ],
                ),
              ),
            ),
            Expanded(
              child: GestureDetector(
                onTap: (){},
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(Icons.public),
                    Text(
                      'Public',
                      style: TextStyle(color: Colors.black),
                    ),
                  ],
                ),
              ),
            ),
            Expanded(
              child: GestureDetector(
                onTap: () {},
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(Icons.sentiment_satisfied),
                    Text(
                      'Settings',
                      style: TextStyle(color: Colors.black),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
      color: AppColors.WHITE,
    );

Case 2 or you can scaffold key

class BottomBar {
  final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
  Widget build(BuildContext context) {
    return Scaffold(
        key: scaffoldKey,
        bottomNavigationBar: BottomAppBar(
          elevation: 10,
          shape: CircularNotchedRectangle(),
          child: Container(
            height: 80,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                Expanded(
                  child: GestureDetector(
                    onTap: () {
                      scaffoldKey.currentState.openDrawer();
                      // scaffoldKey.currentState.openEndDrawer(); // use to open end drawer
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(Icons.dashboard),
                        Text(
                          'DASHBOARD',
                          style: TextStyle(color: Colors.black),
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: GestureDetector(
                    onTap: () {},
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(Icons.home),
                        Text(
                          'CHALLENGES',
                          style: TextStyle(color: Colors.black),
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: GestureDetector(
                    onTap: () {},
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(Icons.public),
                        Text(
                          'Public',
                          style: TextStyle(color: Colors.black),
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: GestureDetector(
                    onTap: () {},
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(Icons.sentiment_satisfied),
                        Text(
                          'Settings',
                          style: TextStyle(color: Colors.black),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          color: AppColors.WHITE,
        ));
  }
}

Tags:

Dart

Flutter