showModalBottomSheet
Shows a modal material design bottom sheet.
A modal bottom sheet is an alternative to a menu or a dialog and prevents the user from interacting with
the
rest of the app.
A closely related widget is a persistent bottom sheet, which shows information that supplements the
primary
content of the app without preventing the use from interacting with the app. Persistent bottom sheets
can be
created and displayed with the showBottomSheet function or the ScaffoldState.showBottomSheet method.
Example :
Scaffold(
appBar: AppBar(
title: const Text("Test"),
),
body: IconButton(
icon: const Icon(Icons.arrow_upward),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (ctx) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Center(child: Text("This a bottom sheet !!")),
Icon(Icons.shutter_speed_outlined)
],
);
});
},
),
);
Note :
The bottom sheet is a StateLessWidget hence we can not call setState or change
state
inside that.
To fix this, we can wrap the Container inside the bottomModalSheet with a StateFullBuilder then we
can call setState inside the bottomModelSheet.
Exercise :
Try to do this using FloatingActionButton, StatefulBuilder, showModalBottomSheet, TextField, DropdownButton and TextButton.
The Solution :
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(
title: 'Hi!',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Color> _colors = [
Colors.green,
Colors.red,
Colors.blue,
Colors.pink,
Colors.orange,
Colors.yellow,
Colors.black
];
String _name = "My Name";
late TextEditingController _nameController;
Color _color = Colors.black;
@override
void initState() {
_nameController = TextEditingController();
super.initState();
}
@override
void dispose() {
_nameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Hi!"),
),
body: Center(
child: Column(
children: [
const SizedBox(
height: 50,
),
CircleAvatar(
backgroundColor: _color,
radius: 50,
child: const Icon(
Icons.person,
size: 50,
)),
Text(
_name,
style: TextStyle(fontSize: 35, color: _color),
)
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.edit),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (ctx, setS) {
return Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: [
TextField(
controller: _nameController,
decoration:
const InputDecoration(labelText: "Name"),
),
Row(
children: [
const Text("Color : "),
DropdownButton(
value: _color,
icon: const Icon(Icons.arrow_downward),
onChanged: (Color? c) {
setState(() {
_color = c!;
});
setS(() {
_color = c!;
});
},
items: _colors
.map<DropdownMenuItem<Color>>((Color c) {
return DropdownMenuItem<Color>(
value: c,
child: Container(
color: c,
width: 60,
height: 20,
),
);
}).toList(),
)
],
),
TextButton(
onPressed: () {
setState(() {
_name = _nameController.text;
Navigator.of(context).pop();
});
},
child: const Text("Update"))
],
),
);
},
);
});
},
),
);
}
}