Search code examples
flutter

Closing BottomSheet of Scaffold if it is open


In one widget, I add a BottomSheet to a Scaffold using the showBottomSheet<T> method.

In another widget, I want to close the BottomSheet if it is open (the BottomSheet may or may not be open when the widget is rendered).

I know you can use Navigator.pop(context); but in my case, the BottomSheet is only rendered in certain scenarios so Navigator.pop(context); would sometimes remove the required screen.

Is there a way to close the bottom sheet using a method that is the inverse of to showBottomSheet<T> (i.e. something in Flutter like a closeBottomSheet<T>)?


Solution

  • You can do it by using Key for your Scaffold. Your showBottomSheet method returns a PersistentBottomSheetController object and this object has a close method and you can use it to trigger the closing.

    I have created a sample above with Key and Global variables to give you an example. It opens up the bottom sheet within one Widget and closes it from the other one.

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Flutter Bottom sheet'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
    PersistentBottomSheetController controller;
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Container(
                height: 200,
                child: Scaffold(
                  key: _scaffoldKey,
                  body: Container(
                    child: RaisedButton(
                      onPressed: () {
                        _settingModalBottomSheet(context);
                      },
                      child: Text("Show Bottom"),
                    ),
                  ),
                ),
              ),
              Container(
                height: 200,
                child: Scaffold(
                  body: Container(
                      child: RaisedButton(
                    onPressed: () {
                      _closeModalBottomSheet();
                    },
                    child: Text("Hide Bottom"),
                  )),
                ),
              ),
            ],
          ),
        );
      }
    }
    
    void _settingModalBottomSheet(context) {
      controller =
          _scaffoldKey.currentState.showBottomSheet<Null>((BuildContext context) {
        return new Container(
            child: new Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            new Padding(
                padding: const EdgeInsets.all(16.0),
                child: new Text(
                  'Some title!',
                  textAlign: TextAlign.left,
                )),
            new Text(
              'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ullamcorper massa metus, sed pharetra mauris porttitor et. Nullam ac ultrices leo. Praesent sed consequat risus. ',
              textAlign: TextAlign.left,
            ),
          ],
        ));
      });
    }
    
    void _closeModalBottomSheet() {
      if (controller != null) {
        controller.close();
        controller = null;
      }
    }