Getting to know Flutter: Advanced use of ModalBottomSheet

Do you want to present a simple modal picker to the user or just show a nice feedback to a user action? In this tutorial you will learn how to use the showModalBottomSheet function.

Let’s start by creating a simple bottom sheet,  with a text and a button. As you can see to close a modal bottom sheet you will use the .pop() function of the Navigator, as you do when closing Scaffold Widgets.

class ModalBottomSheetsPage extends StatelessWidget {
  ModalBottomSheetsPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Modal bottom sheets'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Show modal bottom sheet'),
          onPressed: () => _showBottomSheet(context),
        ),
      ),
    );
  }

  void _showBottomSheet(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (context) => SafeArea(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20.0),
          child: Container(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Text(
                  'This is a Modal bottom sheet!',
                  style: Theme.of(context).textTheme.headline4,
                  textAlign: TextAlign.center,
                ),
                ElevatedButton(
                  child: const Text('Close BottomSheet'),
                  onPressed: () => Navigator.pop(context),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Let’s add some fanciness and sound the top corners of our bottom sheet, this is incredibly easy, you just need to add the shape parameter to the showModalBottomSheet function, specifying the shape that we want to use.

    showModalBottomSheet(
      context: context,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(15)),
      ),
      builder: (context) => SafeArea(

Now we will do a more complex example, we will display in the bottom sheet a list of 100 elements, and the sheet will expand/collapse while the user scrolls through the list. To do so we will use the DraggableScrollableSheet widget. 
This widget has been created to do this types of sheet, it has a builder function that exposes a ScrollController that we will need to use in our ListView to keep the scrolling of the list in sync with the state of the bottom sheet.

In this case we’re also passing the index of the list tile pressed in the pop function, so we could use it later. It will be the result of the Future of the showModalBottomSheet function, and we’re retrieving it awaiting onshowModalBottomSheet

  Future<void> _showBottomSheet(BuildContext context) async {
    int? result = await showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      isDismissible: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(15)),
      ),
      builder: (context) => DraggableScrollableSheet(
        initialChildSize: 0.4,
        minChildSize: 0.2,
        maxChildSize: 0.9,
        expand: false,
        builder: (context, scrollController) => SafeArea(
          child: ListView.builder(
            controller: scrollController,
            itemCount: 100,
            itemBuilder: (context, index) => ListTile(
              title: Text(index.toString()),
              onTap: () => Navigator.of(context).pop(index),
            ),
          ),
        ),
      ),
    );

    print(result);
  }

Add a Comment

Your email address will not be published. Required fields are marked *