Hands-on with Material Components for Android: Dialogs
Part 7 of a series covering practical usage of Material Components for Android
This post will be covering the features and API of Dialog components. To find out how to handle initial setup of Material Components for Android (including the Gradle dependency and creating an app theme), please see my original post:
Dialogs are components, typically with modal windows, that are displayed in front of app content. They are used to inform users about a task that may contain critical information and/or require a decision. They purposefully interrupt the current flow and remain on screen until dismissed or action has been taken, so they should be used sparingly.
From a design perspective, there are three main types of dialogs which can be used in different scenarios:
- Alert dialog: The simplest of dialogs, despite the name. Used to interrupt a user with urgent information that typically requires user action/confirmation. Characterized by a title, optional supporting text and action buttons.
- Simple dialog: Used to present the user with a list of actions that, when tapped, take immediate effect. Should not contain action buttons.
- Confirmation dialog: Used to present a list of single- or multi-select choices to a user. Action buttons serve to confirm the choice(s).
All of the above share common characteristics: a background scrim that obscures app content (which can be optionally tapped to dismiss the dialog) and a surface container.
Note: A fourth type exists: Full screen dialog. To implement this, the official documentation recommends using a DialogFragment
along with resource qualifiers to determine how it is presented. This is outside the scope of this article and won’t be covered.
Basic usage 🏁
All of the aforementioned dialog types can be implemented using MaterialAlertDialogBuilder
. This builder class configures and instantiates an AlertDialog
with Material Design specifications and theming.
The basic method of showing a dialog is like so:
// Note: A second constructor exists to pass in a theme res ID
MaterialAlertDialogBuilder(context)
// Add customization options here
.show()
The above approach will not retain the dialog after a configuration change (such as device rotation). To achieve this we need to use a DialogFragment
while still using MaterialAlertDialogBuilder
to provide the Dialog
:
class AppDialogFragment : DialogFragment() {
override fun onCreateDialog(
savedInstanceState: Bundle?
): Dialog {
return MaterialAlertDialogBuilder(requireContext())
// Add customization options here
.create()
}
}
The DialogFragment
can be shown using the Navigation Architecture Component or manually from a Fragment
or Activity
in the following way:
// Note: A FragmentTransaction can be used in place of the manager
AppDialogFragment().show(requireFragmentManager(), TAG)
Customization using the builder 🧰
All of the characteristics listed in the three types of dialogs above (and more) can be achieved by passing parameters to MaterialAlertDialogBuilder
. Some of these are listed below.
Note: In most cases below, hardcoded values are used. The builder provides overloads for resource IDs as well.
Title and supporting text
// Title
.setTitle("Title")// Supporting text
.setMessage("Supporting text")
Action buttons
// Confirming action
.setPositiveButton("Confirm") { dialog, which ->
// Do something for button click
}// Dismissive action
.setNegativeButton("Dismiss") { dialog, which ->
// Do something for button click
}// Neutral action
.setNeutralButton("Neutral") { dialog, which ->
// Do something for button click
}
Simple items
val items = arrayOf("Item 1", "Item 2", "Item 3").setItems(items) { dialog, which ->
// Do something for item chosen
}
Single- and multi-choice items
val singleItems = arrayOf("Item 1", "Item 2", "Item 3", "Item 4")
val checkedItem = 0// Single-choice items (initialized with checked item)
.setSingleChoiceItems(singleItems, checkedItem) { dialog, which ->
// Do something for item chosen
}val multiItems = arrayOf("Item 1", "Item 2", "Item 3", "Item 4")
val checkedItems = booleanArrayOf(true, false, false, false)// Multi-choice items (initialized with checked items)
.setMultiChoiceItems(items, checkedItems) { dialog, which, checked ->
// Do something for item chosen
}
Icon
.setIcon(R.drawable.ic_android_24dp)
Custom layout/view
.setView(R.layout.view_custom_dialog)
Note: The middle area of the dialog can be occupied by either supporting text or a set of items of a particular type. These cannot be combined.
Choosing a theme overlay 🤔
A couple of theme overlays exist for changing the general layout of a dialog. These theme overlay variants inherit from ThemeOverlay.MaterialComponents.MaterialAlertDialog
, each with an optional suffix:
- Default: No suffix
- Centered:
*.Centered
, center-aligned title and icon
When implementing a global custom Material AlertDialog
theme overlay, reference it in your app theme with the materialAlertDialogTheme
attribute.
Alternatively, there exists a secondary MaterialAlertDialogBuilder
constructor which accepts an overriding theme resource ID:
MaterialAlertDialogBuilder(context, R.style.ThemeOverlay_MaterialComponents_MaterialAlertDialog)
Theming 🎨
Material Alert Dialogs can be themed in terms of the three Material Theming subsystems: color, typography and shape. We have already shown which theme overlays to use in the “Choosing a theme overlay” section above. In addition to this, a custom AlertDialog
style can be referenced within a theme overlay by extending the MaterialAlertDialog.MaterialComponents
style and using the alertDialogStyle
attribute.
Color
There are no specific attributes to customize the colors used in a dialog but the colorPrimary
, colorSecondary
, colorSurface
and respective “on” colors used in your app theme will automatically adjust the dialog colors when changed.
Typography
The dialog text elements will adopt the fontFamily
attribute defined in your app theme. The action buttons will be styled according to the textAppearanceButton
style set in your app theme.
In your theme overlay, you can also use the materialAlertDialogBodyTextStyle
attribute to specifically style the body text.
Shape
The shape of a dialog background can be customized with the shapeAppearance
attribute. This defaults to shapeAppearanceMediumComponent
.
More resources 📚
- The source code for the Playground app used in this article can be found on GitHub.
- Dialogs Design Documentation
- Dialogs API Documentation
I hope this post has provided some insight into dialogs and how they can be used in your Android app(s). If you have any questions, thoughts or suggestions then I’d love to hear from you!
Find me on Twitter @ricknout