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);
}
Top comments (0)