BottomSheet is a built-in widget in Flutter. This widget is very useful in many situations, such as when you want to present some information, display a menu, show a form with text fields, etc.
This article will walk you through 3 distinct examples of implementing BottomSheet in Flutter apps. The first one is about a modal bottom sheet, the second one is about a persistent bottom sheet and the last one is about using a modal bottom sheet with multiple text fields inside. The point of the third example is to solve a common realistic problem: the soft keyboard overlaps the text fields and therefore the user is made it difficult to enter information.
Modal Bottom Sheet
In general, modal bottom sheets are shown by using the showModalBottomSheet function.
Example Preview
The full code
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
theme: ThemeData(
// use Material 3
useMaterial3: true,
primarySwatch: Colors.blue,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
void _show(BuildContext ctx) {
showModalBottomSheet(
elevation: 10,
backgroundColor: Colors.amber,
context: ctx,
builder: (ctx) => Container(
width: 300,
height: 250,
color: Colors.white54,
alignment: Alignment.center,
child: const Text('Breathe in... Breathe out...'),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Kindacode.com'),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
child: const Text('Show The BottomSheet'),
onPressed: () => _show(context),
),
),
),
);
}
}
Persistent Bottom Sheet
Note: This persistent bottom sheet remains visible even when the user interacts with other parts of the app. It isn’t a LocalHistoryEntry and cannot be dismissed with Navigator.of(context).pop() or the scaffold appBar’s back button.
Example Preview
The code
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
theme: ThemeData(
// enable Material 3
useMaterial3: true,
primarySwatch: Colors.blue,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
bool _showBottomSheet = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Kindacode.com'),
),
body: Container(),
// The bottom sheet here
bottomSheet: _showBottomSheet
? BottomSheet(
elevation: 10,
backgroundColor: Colors.amber,
enableDrag: false,
onClosing: () {},
builder: (BuildContext ctx) => Container(
width: double.infinity,
height: 250,
alignment: Alignment.center,
child: ElevatedButton(
child: const Text(
'Close this bottom sheet',
),
onPressed: () {
setState(() {
_showBottomSheet = false;
});
},
),
))
: null,
);
}
}
Modal Bottom Sheet with Text Fields inside
Example Preview
This example creates a modal bottom sheet with some text fields and a button that lets users submit some information. You will notice that when the soft keyboard shows up, the bottom sheet will move up too, so the text fields will not be covered.
Set the isScrollControlled parameter of the showModalBottomSheet function to true and add an extra padding-bottom equal to or greater than MediaQuery.of(context).viewInsets.bottom makes things work fine.
The full code
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
// This function is triggered when the floating buttion is pressed
void _show(BuildContext ctx) {
showModalBottomSheet(
isScrollControlled: true,
elevation: 5,
context: ctx,
builder: (ctx) => Padding(
padding: EdgeInsets.only(
top: 15,
left: 15,
right: 15,
bottom: MediaQuery.of(ctx).viewInsets.bottom + 15),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const TextField(
keyboardType: TextInputType.name,
decoration: InputDecoration(labelText: 'Name'),
),
const TextField(
keyboardType: TextInputType.number,
decoration: InputDecoration(labelText: 'Age'),
),
const SizedBox(
height: 15,
),
ElevatedButton(onPressed: () {}, child: const Text('Submit'))
],
),
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Kindacode.com'),
),
body: Container(),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () => _show(context),
),
);
}
}
Wrap Up
This article walked you through a few examples of working with BottomSheet in Flutter. Continue learning more new and interesting stuff by taking a look at the following articles: Flutter and Firestore Database: CRUD example, Example of sortable DataTable in Flutter, Working with Time Picker in Flutter, Working with Cupertino Date Picker in Flutter, Working with AlertDialog in Flutter, Flutter & SQLite: CRUD Example.
You can also check out our Flutter topic page or Dart topic page for the latest tutorials and examples.