Android Development
Yes/No Dialog
Android UI
Dialog Box
Android Programming

How to display a Yes/No dialog box on Android?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Confirmation dialogs are one of the most common UI patterns in Android apps. Whether you need to confirm a deletion, prompt a user to save changes, or ask for permission, a simple Yes/No dialog does the job. Android provides several ways to build one, and the best choice depends on your architecture and the UI toolkit you are using.

AlertDialog.Builder with Kotlin

The classic approach uses AlertDialog.Builder. You set a title, a message, and two buttons — one for the positive action and one for the negative action.

kotlin
1AlertDialog.Builder(this)
2    .setTitle("Confirm Delete")
3    .setMessage("Are you sure you want to delete this item?")
4    .setPositiveButton("Yes") { dialog, _ ->
5        // handle the "Yes" action
6        deleteItem()
7        dialog.dismiss()
8    }
9    .setNegativeButton("No") { dialog, _ ->
10        dialog.dismiss()
11    }
12    .setCancelable(false)
13    .show()

Setting setCancelable(false) prevents the user from dismissing the dialog by tapping outside of it, which is useful when you need an explicit answer.

AlertDialog.Builder with Java

The same pattern works in Java. The main difference is the lambda syntax for click listeners.

java
1new AlertDialog.Builder(this)
2    .setTitle("Confirm Delete")
3    .setMessage("Are you sure you want to delete this item?")
4    .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
5        @Override
6        public void onClick(DialogInterface dialog, int which) {
7            deleteItem();
8            dialog.dismiss();
9        }
10    })
11    .setNegativeButton("No", new DialogInterface.OnClickListener() {
12        @Override
13        public void onClick(DialogInterface dialog, int which) {
14            dialog.dismiss();
15        }
16    })
17    .setCancelable(false)
18    .show();

Both the Kotlin and Java versions produce the same result at runtime. The Kotlin version is shorter because SAM conversions turn the OnClickListener interface into a lambda automatically.

MaterialAlertDialogBuilder

If your app uses Material Design (and most modern apps should), replace AlertDialog.Builder with MaterialAlertDialogBuilder from the Material Components library. It follows the latest Material theming guidelines automatically.

kotlin
1MaterialAlertDialogBuilder(this)
2    .setTitle("Discard draft?")
3    .setMessage("Any unsaved changes will be lost.")
4    .setPositiveButton("Discard") { dialog, _ ->
5        discardDraft()
6    }
7    .setNegativeButton("Keep editing") { dialog, _ ->
8        dialog.dismiss()
9    }
10    .show()

Add the dependency in your build.gradle if you have not already:

groovy
implementation 'com.google.android.material:material:1.12.0'

MaterialAlertDialogBuilder is a drop-in replacement; every method available on AlertDialog.Builder works the same way.

DialogFragment for Lifecycle Safety

Creating an AlertDialog directly inside an Activity or Fragment can cause crashes if the dialog is still visible during a configuration change (such as a screen rotation). Wrapping the dialog in a DialogFragment ties it to the Android lifecycle so the system can recreate it automatically.

kotlin
1class ConfirmDeleteDialogFragment : DialogFragment() {
2
3    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
4        return MaterialAlertDialogBuilder(requireContext())
5            .setTitle("Confirm Delete")
6            .setMessage("This action cannot be undone.")
7            .setPositiveButton("Yes") { _, _ ->
8                // communicate result back to the caller
9                parentFragmentManager.setFragmentResult(
10                    "confirmDelete",
11                    bundleOf("confirmed" to true)
12                )
13            }
14            .setNegativeButton("No") { dialog, _ ->
15                dialog.dismiss()
16            }
17            .create()
18    }
19}

Show the dialog from your Activity or Fragment:

kotlin
ConfirmDeleteDialogFragment().show(supportFragmentManager, "confirmDelete")

The caller listens for the result using the Fragment Result API, keeping the dialog decoupled from the host.

Jetpack Compose AlertDialog

In Compose-based UIs you do not use AlertDialog.Builder at all. Instead you use the AlertDialog composable, controlling visibility through state.

kotlin
1@Composable
2fun ConfirmDeleteDialog(
3    showDialog: Boolean,
4    onConfirm: () -> Unit,
5    onDismiss: () -> Unit
6) {
7    if (showDialog) {
8        AlertDialog(
9            onDismissRequest = onDismiss,
10            title = { Text("Confirm Delete") },
11            text = { Text("Are you sure you want to delete this item?") },
12            confirmButton = {
13                TextButton(onClick = onConfirm) {
14                    Text("Yes")
15                }
16            },
17            dismissButton = {
18                TextButton(onClick = onDismiss) {
19                    Text("No")
20                }
21            }
22        )
23    }
24}

In the calling composable, manage the dialog state with remember:

kotlin
1var showDialog by remember { mutableStateOf(false) }
2
3Button(onClick = { showDialog = true }) {
4    Text("Delete")
5}
6
7ConfirmDeleteDialog(
8    showDialog = showDialog,
9    onConfirm = {
10        deleteItem()
11        showDialog = false
12    },
13    onDismiss = { showDialog = false }
14)

The Compose approach is fully declarative — the dialog appears and disappears based on a boolean state value, which makes it easy to test and reason about.

Common Pitfalls

  • Creating an AlertDialog directly in an Activity without a DialogFragment, which leads to window-leaked exceptions during configuration changes like screen rotation.
  • Forgetting to call show() at the end of the builder chain, resulting in a dialog that is constructed but never displayed.
  • Using AlertDialog.Builder instead of MaterialAlertDialogBuilder in a Material-themed app, causing the dialog to look inconsistent with the rest of the UI.
  • Passing null as the click listener for the negative button instead of an explicit dismiss handler, which can confuse readers of the code about whether the tap is intentionally a no-op.
  • Managing Compose dialog visibility with a plain variable rather than a MutableState, so recomposition never triggers and the dialog never appears.

Summary

  • Use AlertDialog.Builder for simple Yes/No prompts in traditional View-based Android apps.
  • Prefer MaterialAlertDialogBuilder to get Material Design theming out of the box.
  • Wrap dialogs in a DialogFragment to survive configuration changes and avoid lifecycle-related crashes.
  • In Jetpack Compose, use the AlertDialog composable with boolean state to show and hide the dialog declaratively.
  • Always decide whether the dialog should be cancelable; set setCancelable(false) or onDismissRequest deliberately based on the required user experience.

Course illustration
Course illustration

All Rights Reserved.