13 KiB
Dialogs
Dialogs inform users about a task and can contain critical information, require decisions, or involve multiple tasks.
Contents
Using dialogs
A dialog is a type of modal window that appears in front of app content to provide critical information or ask for a decision. Dialogs disable all app functionality when they appear, and remain on screen until confirmed, dismissed, or a required action has been taken.
Dialogs are purposefully interruptive, so they should be used sparingly.
Before you can use Material dialogs, you need to import the Material Components package for Flutter: package:flutter/material.dart.
You need to use a MaterialApp.
For more information on getting started with the Material for Flutter, go to the Flutter Material library page.
Types
There are four types of dialogs: 1. Alert, 2. Simple, 3. Confirmation, 4. Full-screen
Making dialogs accessible
Flutter's APIs support accessibility setting for large fonts, screen readers, and sufficient contrast. For more information, go to Flutter's accessibility and internationalization pages.
For more guidance on writing labels, go to our page on how to write a good accessibility label.
Alert dialog
Alert dialogs interrupt users with urgent information, details, or actions.
Alert dialog example
AlertDialog
The following example shows an alert dialog.
AlertDialog(
title: Text('Reset settings?'),
content: Text('This will reset your device to its default factory settings.'),
actions: [
FlatButton(
textColor: Color(0xFF6200EE),
onPressed: () {},
child: Text('CANCEL'),
),
FlatButton(
textColor: Color(0xFF6200EE),
onPressed: () {},
child: Text('ACCEPT'),
),
],
)
Alert dialog anatomy and key properties
The alert dialog contains the following:
- Container
- Title (optional)
- Supporting text
- Buttons
- Scrim
Container attributes
| Properties | |
|---|---|
| Color | backgroundColor |
| Shape | shape |
| Elevation | elevation |
Title attributes
| Properties | |
|---|---|
| Text label | title |
| Color | style on title when using a Text |
| Typography | style on title when using a Text |
Supporting text attributes
| Properties | |
|---|---|
| Text label | content |
| Color | style on content when using a Text |
| Typography | style on content when using a Text |
Buttons attributes
| Properties | |
|---|---|
| Buttons | actions |
Simple dialog
Simple dialogs can display items that are immediately actionable when selected. They don’t have text buttons.
As simple dialogs are interruptive, they should be used sparingly. Alternatively, dropdown menus provide options in a non-modal, less disruptive way.
Simple dialog example
SimpleDialog
The following example shows a simple dialog.
SimpleDialog(
title: Text('Set backup account'),
children: [
SimpleDialogItem(
icon: Icons.account_circle,
color: Colors.orange,
text: 'user01@gmail.com',
onPressed: () {
Navigator.pop(context, 'user01@gmail.com');
},
),
SimpleDialogItem(
icon: Icons.account_circle,
color: Colors.green,
text: 'user02@gmail.com',
onPressed: () {
Navigator.pop(context, 'user02@gmail.com');
},
),
SimpleDialogItem(
icon: Icons.add_circle,
color: Colors.grey,
text: 'Add account',
onPressed: () {
Navigator.pop(context, 'user02@gmail.com');
},
),
],
)
class SimpleDialogItem extends StatelessWidget {
const SimpleDialogItem({Key key, this.icon, this.color, this.text, this.onPressed})
: super(key: key);
final IconData icon;
final Color color;
final String text;
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return SimpleDialogOption(
onPressed: onPressed,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(icon, size: 36.0, color: color),
Padding(
padding: const EdgeInsetsDirectional.only(start: 16.0),
child: Text(text),
),
],
),
);
}
}
Simple dialog anatomy and key properties
A simple dialog contains the following:
- Container
- Title
- List item
- Supporting visual
- Primary text
- Button
- Scrim
Container attributes
| Properties | |
|---|---|
| Color | backgroundColor |
| Shape | shape |
| Elevation | elevation |
Title attributes
| Properties | |
|---|---|
| Text label | title |
| Color | style on title when using a Text |
| Typography | style on title when using a Text |
List item supporting visual attributes
| Properties | |
|---|---|
| Options | children (Use SimpleDialogOption and customize its child parameter as needed.) |
Confirmation dialog
Confirmation dialogs give users the ability to provide final confirmation of a choice before committing to it, so they have a chance to change their minds if necessary.
If the user confirms a choice, it’s carried out. Otherwise, the user can dismiss the dialog. For example, users can listen to multiple ringtones but only make a final selection upon tapping “OK.”
NOTE: There is no explicit confirmation dialog in Flutter but this can be built using the Dialog widget as a blank slate and providing your own custom child.
Full-screen dialog
Full-screen dialogs group a series of tasks, such as creating a calendar entry with the event title, date, location, and time. Because they take up the entire screen, full-screen dialogs are the only dialogs over which other dialogs can appear.
Full-screen dialog example
MaterialPageRoute
To use a full-screen dialog, simply set the fullscreenDialog to true when pushing a new MaterialPageRoute.
Full-screen dialog anatomy
The full-screen dialog contains the following properties:
- Title
- Icon Button
- Buttons
- Scrim
Dialog theming
Dialog theming example
The following example shows a simple dialog with the Material Shrine Theme.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
home: MyHomePage(),
theme: _buildShrineTheme(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final AlertDialog dialog = AlertDialog(
title: Text('Title'),
contentPadding: EdgeInsets.zero,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
for (int i = 1; i <= 3; i++)
ListTile(
title: Text(
'option $i',
style: Theme.of(context)
.textTheme
.subtitle1
.copyWith(color: shrineBrown900),
),
leading: Radio(
value: i,
groupValue: 1,
onChanged: (_) {},
),
),
],
),
actions: [
FlatButton(
textColor: shrineBrown900,
onPressed: () => Navigator.pop(context),
child: Text('ACTION 1'),
),
FlatButton(
textColor: shrineBrown900,
onPressed: () => Navigator.pop(context),
child: Text('ACTION 2'),
),
],
);
return Scaffold(
body: Center(
child: FlatButton(
onPressed: () {
showDialog<void>(context: context, builder: (context) => dialog);
},
child: Text("SHOW DIALOG"),
),
),
);
}
}
ThemeData _buildShrineTheme() {
final ThemeData base = ThemeData.light();
return base.copyWith(
colorScheme: _shrineColorScheme,
toggleableActiveColor: shrinePink400,
accentColor: shrineBrown900,
primaryColor: shrinePink100,
buttonColor: shrinePink100,
scaffoldBackgroundColor: shrineBackgroundWhite,
cardColor: shrineBackgroundWhite,
textSelectionTheme: TextSelectionThemeData(selectionColor: shrinePink100),
errorColor: shrineErrorRed,
buttonTheme: const ButtonThemeData(
colorScheme: _shrineColorScheme,
textTheme: ButtonTextTheme.normal,
),
primaryIconTheme: _customIconTheme(base.iconTheme),
textTheme: _buildShrineTextTheme(base.textTheme),
primaryTextTheme: _buildShrineTextTheme(base.primaryTextTheme),
accentTextTheme: _buildShrineTextTheme(base.accentTextTheme),
iconTheme: _customIconTheme(base.iconTheme),
dialogTheme: DialogTheme(
backgroundColor: shrinePink100,
),
);
}
IconThemeData _customIconTheme(IconThemeData original) {
return original.copyWith(color: shrineBrown900);
}
TextTheme _buildShrineTextTheme(TextTheme base) {
return base
.copyWith(
caption: base.caption.copyWith(
fontWeight: FontWeight.w400,
fontSize: 14,
letterSpacing: defaultLetterSpacing,
),
button: base.button.copyWith(
fontWeight: FontWeight.w500,
fontSize: 14,
letterSpacing: defaultLetterSpacing,
),
)
.apply(
fontFamily: 'Rubik',
displayColor: shrineBrown900,
bodyColor: shrineBrown900,
);
}
const ColorScheme _shrineColorScheme = ColorScheme(
primary: shrinePink100,
primaryVariant: shrineBrown900,
secondary: shrineBrown900,
secondaryVariant: shrineBrown900,
surface: shrineSurfaceWhite,
background: shrineBackgroundWhite,
error: shrineErrorRed,
onPrimary: shrineBrown900,
onSecondary: shrineBrown900,
onSurface: shrineBrown900,
onBackground: shrineBrown900,
onError: shrineSurfaceWhite,
brightness: Brightness.light,
);
const Color shrinePink50 = Color(0xFFFEEAE6);
const Color shrinePink100 = Color(0xFFFEDBD0);
const Color shrinePink300 = Color(0xFFFBB8AC);
const Color shrinePink400 = Color(0xFFEAA4A4);
const Color shrineBrown900 = Color(0xFF442B2D);
const Color shrineBrown600 = Color(0xFF7D4F52);
const Color shrineErrorRed = Color(0xFFC5032B);
const Color shrineSurfaceWhite = Color(0xFFFFFBFA);
const Color shrineBackgroundWhite = Colors.white;
const defaultLetterSpacing = 0.03;







