11

I'm trying to implement a bottom navigation drawer, similar to the one used in the Reply Material Study, that is an extension of the bottom app bar, and opened and closed via an icon button in the bottom app bar.

Bottom Navigation Drawer for Reply

I've tried bottom sheets, but that replaces, or hovers on top of, the bottom app bar. I want it to look like the one in the screenshot where the bottom app bar stays on the screen and the bottom navigation drawer slides up when the "menu" button is tapped.

The Material Design site shows this as a component, but doesn't link off to anywhere showing how to implement it in Flutter.

1
  • Could you please link the Material Design page? All I can find on there is this: storage.googleapis.com/spec-host-backup/…, which shows the Bottom Drawer covering the BottomAppBar... Commented Jan 14, 2019 at 21:18

3 Answers 3

24

I quickly made it, but you are going to have to implement active page text/icon colors to the listview. Also, the full code is here if you want to copy from the gist.

enter image description here

class ScreenOne extends StatefulWidget {
  @override
  _ScreenOneState createState() => _ScreenOneState();
}

class _ScreenOneState extends State<ScreenOne> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Reply demo"),
      ),
      bottomNavigationBar: BottomAppBar(
        elevation: 0,
        color: Color(0xff344955),
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: 10.0),
          height: 56.0,
          child: Row(children: <Widget>[
            IconButton(
              onPressed: showMenu,
              icon: Icon(Icons.menu),
              color: Colors.white,
            ),
            Spacer(),
            IconButton(
              onPressed: () {},
              icon: Icon(Icons.add),
              color: Colors.white,
            )
          ]),
        ),
      ),
    );
  }

  showMenu() {
    showModalBottomSheet(
        context: context,
        builder: (BuildContext context) {
          return Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.only(
                topLeft: Radius.circular(16.0),
                topRight: Radius.circular(16.0),
              ),
              color: Color(0xff232f34),
            ),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.end,
              children: <Widget>[
                Container(
                  height: 36,
                ),
                SizedBox(
                    height: (56 * 6).toDouble(),
                    child: Container(
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.only(
                            topLeft: Radius.circular(16.0),
                            topRight: Radius.circular(16.0),
                          ),
                          color: Color(0xff344955),
                        ),
                        child: Stack(
                          alignment: Alignment(0, 0),
                          overflow: Overflow.visible,
                          children: <Widget>[
                            Positioned(
                              top: -36,
                              child: Container(
                                decoration: BoxDecoration(
                                    borderRadius:
                                        BorderRadius.all(Radius.circular(50)),
                                    border: Border.all(
                                        color: Color(0xff232f34), width: 10)),
                                child: Center(
                                  child: ClipOval(
                                    child: Image.network(
                                      "https://i.sstatic.net/S11YG.jpg?s=64&g=1",
                                      fit: BoxFit.cover,
                                      height: 36,
                                      width: 36,
                                    ),
                                  ),
                                ),
                              ),
                            ),
                            Positioned(
                              child: ListView(
                                physics: NeverScrollableScrollPhysics(),
                                children: <Widget>[
                                  ListTile(
                                    title: Text(
                                      "Inbox",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    leading: Icon(
                                      Icons.inbox,
                                      color: Colors.white,
                                    ),
                                    onTap: () {},
                                  ),
                                  ListTile(
                                    title: Text(
                                      "Starred",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    leading: Icon(
                                      Icons.star_border,
                                      color: Colors.white,
                                    ),
                                    onTap: () {},
                                  ),
                                  ListTile(
                                    title: Text(
                                      "Sent",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    leading: Icon(
                                      Icons.send,
                                      color: Colors.white,
                                    ),
                                    onTap: () {},
                                  ),
                                  ListTile(
                                    title: Text(
                                      "Trash",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    leading: Icon(
                                      Icons.delete_outline,
                                      color: Colors.white,
                                    ),
                                    onTap: () {},
                                  ),
                                  ListTile(
                                    title: Text(
                                      "Spam",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    leading: Icon(
                                      Icons.error,
                                      color: Colors.white,
                                    ),
                                    onTap: () {},
                                  ),
                                  ListTile(
                                    title: Text(
                                      "Drafts",
                                      style: TextStyle(color: Colors.white),
                                    ),
                                    leading: Icon(
                                      Icons.mail_outline,
                                      color: Colors.white,
                                    ),
                                    onTap: () {},
                                  ),
                                ],
                              ),
                            )
                          ],
                        ))),
                Container(
                  height: 56,
                  color: Color(0xff4a6572),
                )
              ],
            ),
          );
        });
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I tried a modal bottom sheet, but I couldn't get it to slide in from under the bottom app bar. It sounds like I'll have to replace the bottom app bar with another widget that I want to show while the bottom sheet is on the screen. I'm assuming that the last Container in your implementation, with height of 56, is your replacement for the bottom app bar.
Yes, there's no way to show the bottom sheet under the bottom app bar within my knowledge. This container with height 56 is the placeholder for the bottom app bar in the bottom sheet. But you don't have to use BottomAppBar widget, just keep the container with row in it.
It looks great, but I think the rounded corners only work if you have a black background screen. I want to display the bottom sheet over a google maps. So the google maps is the background, and then the way you do the rounded corners won't work (just as a hint for other people thinking to use this code)
5

You can use BottomSheet . (Thanks to westdabestdb)

Working on flutter_gallery demo app:

class ModalBottomSheetDemo extends StatelessWidget {
  static const String routeName = '/material/modal-bottom-sheet';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Modal bottom sheet'),
        actions: <Widget>[MaterialDemoDocumentationButton(routeName)],
      ),
      body: Center(
        child: RaisedButton(
          child: const Text('SHOW BOTTOM SHEET'),
          onPressed: () {
            showModalBottomSheet<void>(context: context, builder: (BuildContext context) {
              return Container(
                child: Padding(
                  padding: const EdgeInsets.all(32.0),
                  child: Text('This is the modal bottom sheet. Tap anywhere to dismiss.',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                      color: Theme.of(context).accentColor,
                      fontSize: 24.0
                    )
                  )
                )
              );
            });
          }
        )
      )
    );
  }
}

5 Comments

Sure that. But no built-in widget (pre-made widget, like dawer, floattingActionButton, tabBar, etc).
imgur.com/14ietCR This is the bottom navigation drawer I built for my 4chan reader app.
great. congrats. what widgets you use to do that ?
BottomSheet and ListView :)
0

Building up on westdabestdb's answer and this article: If you want a bottom navigation drawer that is not blocking, with rounded corners and that is not depending on a black background, try this:

class GoogleMapsHomeUI extends StatelessWidget {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

@override
Widget build(BuildContext context) {

  showBottomDrawer();

  return Scaffold(
    key: scaffoldKey, // use the key to reference the Scaffold from outside
    ... the rest of your background Scaffold
  );
}


void showBottomDrawer() {
// the next line is needed, because the Scaffold needs to be finished before this function continues.
WidgetsBinding.instance.addPostFrameCallback((_) {
  PersistentBottomSheetController? bottomSheetController = scaffoldKey.currentState?.showBottomSheet((BuildContext context) {
  return Container(
        height: 300,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.only( // makes the round corners
            topLeft: Radius.circular(20.0),
            topRight: Radius.circular(20.0),
          ),
          color: Color(0xff232f34),
        ),
        child:  Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.end,
            children: <Widget>[
              Container(
                height: 36,
              ),
              SizedBox(
                  height: (56 * 6).toDouble(),
                  child: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.only(
                          topLeft: Radius.circular(16.0),
                          topRight: Radius.circular(16.0),
                        ),
                        color: Color(0xff344955),
                      ),
                      child: Stack(
                        alignment: Alignment(0, 0),
                        children: <Widget>[
                          Positioned(
                            top: -36,
                            child: Container(
                              decoration: BoxDecoration(
                                  borderRadius:
                                  BorderRadius.all(Radius.circular(50)),
                                  border: Border.all(
                                      color: Color(0xff232f34), width: 10)),
                              child: Center(
                                child: ClipOval(
                                  child: Image.network(
                                    "https://i.sstatic.net/S11YG.jpg?s=64&g=1",
                                    fit: BoxFit.cover,
                                    height: 36,
                                    width: 36,
                                  ),
                                ),
                              ),
                            ),
                          ),
                          Positioned(
                            child: ListView(
                              physics: NeverScrollableScrollPhysics(),
                              children: <Widget>[
                                ListTile(
                                  title: Text(
                                    "Inbox",
                                    style: TextStyle(color: Colors.white),
                                  ),
                                  leading: Icon(
                                    Icons.inbox,
                                    color: Colors.white,
                                  ),
                                  onTap: () {},
                                ),
                                ListTile(
                                  title: Text(
                                    "Starred",
                                    style: TextStyle(color: Colors.white),
                                  ),
                                  leading: Icon(
                                    Icons.star_border,
                                    color: Colors.white,
                                  ),
                                  onTap: () {},
                                ),
                                ListTile(
                                  title: Text(
                                    "Sent",
                                    style: TextStyle(color: Colors.white),
                                  ),
                                  leading: Icon(
                                    Icons.send,
                                    color: Colors.white,
                                  ),
                                  onTap: () {},
                                ),
                                ListTile(
                                  title: Text(
                                    "Trash",
                                    style: TextStyle(color: Colors.white),
                                  ),
                                  leading: Icon(
                                    Icons.delete_outline,
                                    color: Colors.white,
                                  ),
                                  onTap: () {},
                                ),
                                ListTile(
                                  title: Text(
                                    "Spam",
                                    style: TextStyle(color: Colors.white),
                                  ),
                                  leading: Icon(
                                    Icons.error,
                                    color: Colors.white,
                                  ),
                                  onTap: () {},
                                ),
                                ListTile(
                                  title: Text(
                                    "Drafts",
                                    style: TextStyle(color: Colors.white),
                                  ),
                                  leading: Icon(
                                    Icons.mail_outline,
                                    color: Colors.white,
                                  ),
                                  onTap: () {},
                                ),
                              ],
                            ),
                          )
                        ],
                      ))),
              Container(
                height: 56,
                color: Color(0xff4a6572),
              )
            ],
          ),
        ),
      ),
     ); // Container
    },  
    backgroundColor: Colors.black,
    elevation: 5,
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.only(topLeft: Radius.circular(15.0), topRight: Radius.circular(15.0)),
    ), clipBehavior: null,
    enableDrag: true,
);

result (I'm not finished with the background yet, but you can interact with the background, while the drawer is open):

bottom drawer

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.