Pierre-Louis 61362ec84c
Replace some deprecated properties (#105)
* 1

* Update pubspec.yaml
2021-05-17 15:50:09 +02:00

13 KiB
Raw Permalink Blame History

Dialogs

Dialogs inform users about a task and can contain critical information, require decisions, or involve multiple tasks.

Dialogs Hero

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

Hero image of the 4 types of dialogs

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.

"Alert dialog example for Flutter."

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:

alert dialog anatomy diagram

  1. Container
  2. Title (optional)
  3. Supporting text
  4. Buttons
  5. 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 dont 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.

"Simple dialog example for Flutter."

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:

simple dialog anatomy diagram

  1. Container
  2. Title
  3. List item
    1. Supporting visual
    2. Primary text
  4. Button
  5. 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, its 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:

full-screen dialog anatomy

  1. Title
  2. Icon Button
  3. Buttons
  4. Scrim

Dialog theming

Dialog theming example

The following example shows a simple dialog with the Material Shrine Theme.

Simple dialog with Shrine theming

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;