Dialogs, Toast & Snackbar
Not every message TrailLog shows the user needs the same weight. Some are just a quick "it worked,"
some offer a brief chance to undo, and some genuinely need a decision before anything proceeds. Android
gives you three different tools for exactly these three cases: Toast,
Snackbar, and AlertDialog. This lesson covers all three, with a clear rule
for when to reach for each.
Toast: A Brief, Non-Interactive Message
A Toast is a small popup that appears briefly and disappears on its own — the user can't interact with it, and it doesn't require any response. It's the right tool purely for confirming that something happened, with nothing further for the user to do about it:
fun onTrailSaved() {
Toast.makeText(context, "Trail saved!", Toast.LENGTH_SHORT).show()
}
Toast.makeText() takes a Context, the message, and a duration constant —
Toast.LENGTH_SHORT or Toast.LENGTH_LONG — and .show() actually
displays it. Nothing about a Toast is anchored to any particular view on screen, which is exactly why
it's unsuitable for anything the user might want to act on: there's no button, and no reliable way to
attach one.
Snackbar: Informational, With an Optional Action
A Snackbar is Material Design's improved alternative to Toast for most in-app
feedback. It appears anchored to the bottom of the screen (properly positioned above a
BottomNavigationView or FloatingActionButton when anchored to a
CoordinatorLayout or any view within one), and — unlike a Toast — it can include a single
action button. Here's TrailLog showing an Undo option right after a trail is deleted, a genuinely
common and well-liked pattern in real apps:
private fun deleteTrail(trail: Trail, position: Int) {
val removedTrail = trail
trailAdapter.removeAt(position)
Snackbar.make(binding.root, "Trail deleted", Snackbar.LENGTH_LONG)
.setAction("Undo") {
trailAdapter.restoreAt(position, removedTrail)
}
.show()
}
Snackbar.make(binding.root, ...) anchors the Snackbar to the given view — usually the
screen's root layout — so Android can position it correctly above any bottom bars or floating buttons
already on screen. .setAction("Undo") { ... } attaches the button and the lambda that
runs if the user taps it; if they don't tap anything before LENGTH_LONG elapses, the
trail simply stays deleted. This is exactly the shape of feedback that suits an optional, reversible
action — informational, but with a graceful way back.
AlertDialog: When a Decision Is Required
An AlertDialog is a modal dialog: it blocks interaction with the rest of the screen
until the user responds. Reach for it only when the app genuinely can't proceed without an answer —
for TrailLog, that's confirming a permanent delete, where an Undo Snackbar wouldn't be
appropriate because the action can't be quietly reversed. Use MaterialAlertDialogBuilder
specifically — the Material-themed version — rather than the plain AlertDialog.Builder,
so the dialog matches the rest of TrailLog's Material styling:
private fun confirmPermanentDelete(trail: Trail) {
MaterialAlertDialogBuilder(requireContext())
.setTitle("Delete trail?")
.setMessage("This will permanently remove \"${trail.name}\". This cannot be undone.")
.setPositiveButton("Delete") { _, _ ->
viewModel.permanentlyDelete(trail)
}
.setNegativeButton("Cancel", null)
.show()
}
The dialog stays on screen until the user taps either button — there's no dismissing it by accident,
and no default action taken silently. Passing null as the listener for
setNegativeButton() is a common, valid pattern: "Cancel" only needs to close the dialog,
which happens automatically, so no extra code is needed for that button.
Choosing the Right One
| Tool | Use When |
|---|---|
Toast | Purely informational — the user doesn't need to act on it, and there's nothing to undo. |
Snackbar | Informational, but with an optional action — most commonly an Undo — that the user can ignore and it quietly goes away. |
AlertDialog | The app genuinely needs the user's decision before it can safely proceed, especially before an irreversible action. |
BottomSheetDialogFragment: A More Substantial Alternative
When a decision needs more room than a simple two-button dialog — say, letting the user pick a sort
order for the trail list, or choose between several export formats — a
BottomSheetDialogFragment is often a better fit than either an
AlertDialog or navigating to an entirely new screen. It slides up from the bottom of the
screen as its own Fragment, showing a larger set of options or even a short form, while the screen
underneath stays visible and the user never technically leaves the current screen. It's a heavier tool
than a Snackbar or a plain dialog, reserved for exactly the cases where those two feel too small.