💬 AlertDialog en Jetpack Compose

Crea diálogos de confirmación y alertas

🎥 Video Tutorial

Aprende paso a paso cómo crear AlertDialogs en Compose:

¿Qué es un AlertDialog?

Un AlertDialog es una ventana emergente que interrumpe el flujo de la aplicación para solicitar una acción del usuario, como confirmar una operación o mostrar información importante.

Ejemplo Visual de un AlertDialog:

Título del Diálogo
Este es el mensaje que explica la acción que se va a realizar. ¿Deseas continuar?

✅ Confirmar acciones

Eliminar datos, cerrar sesión, salir de la app

ℹ️ Mostrar información

Alertas, avisos, mensajes importantes

⚠️ Advertencias

Errores, validaciones, confirmaciones críticas

1️⃣ Paso 1: Crear Variable de Estado

Necesitamos una variable que controle cuándo mostrar u ocultar el diálogo:

var mostrarDialogo by rememberSaveable { mutableStateOf(false) }
💡 Estado del diálogo:
  • false → El diálogo está oculto (por defecto)
  • true → El diálogo se muestra en pantalla
  • Usamos rememberSaveable para mantener el estado durante rotaciones

2️⃣ Paso 2: Botón para Mostrar el Diálogo

Creamos un botón que cambia el estado a true cuando se presiona:

Button(
    onClick = {
        mostrarDialogo = true
    }
) {
    Text(text = "Mostrar Diálogo")
}
✅ Flujo básico:
  1. Usuario presiona el botón
  2. Se ejecuta mostrarDialogo = true
  3. El estado cambia y la UI se recompone
  4. El diálogo aparece en pantalla

3️⃣ Paso 3: Crear el AlertDialog

Cuando mostrarDialogo es true, mostramos el AlertDialog:

if (mostrarDialogo) {
    AlertDialog(
        title = {
            Text("Título del Diálogo")
        },
        text = {
            Text("¿Estás seguro de realizar esta acción?")
        },
        confirmButton = {
            TextButton(
                onClick = {
                    // Acción al confirmar
                    mostrarDialogo = false
                }
            ) {
                Text("Aceptar")
            }
        },
        dismissButton = {
            TextButton(
                onClick = {
                    // Acción al cancelar
                    mostrarDialogo = false
                }
            ) {
                Text("Cancelar")
            }
        },
        onDismissRequest = {
            // Se ejecuta al tocar fuera o botón atrás
            mostrarDialogo = false
        }
    )
}
📋 Parámetros del AlertDialog:
  • title: Título del diálogo (opcional pero recomendado)
  • text: Mensaje o descripción (opcional)
  • confirmButton: Botón de confirmación (obligatorio)
  • dismissButton: Botón de cancelación (opcional)
  • onDismissRequest: Se ejecuta al tocar fuera del diálogo o presionar atrás (obligatorio)

🔍 Parámetros Explicados

1 confirmButton

Botón principal que confirma la acción. Generalmente cierra el diálogo y ejecuta la operación solicitada. En nuestro caso, simplemente oculta el diálogo con mostrarDialogo = false.

2 dismissButton

Botón secundario que cancela la acción. Cierra el diálogo sin ejecutar la operación principal. También establece mostrarDialogo = false.

3 onDismissRequest

Lambda que se ejecuta cuando el usuario toca fuera del diálogo o presiona el botón de retroceso. Es obligatorio para permitir que el usuario pueda cerrar el diálogo de estas formas.

⚠️ Importante:

Siempre debes cambiar mostrarDialogo = false en los tres lugares (confirmButton, dismissButton y onDismissRequest) para que el diálogo se cierre correctamente en todos los casos.

🔧 Función Composable Reutilizable

Creamos una función reutilizable para no repetir código:

@Composable
fun AlertDialogUi(
    title: String,
    message: String,
    confirmButton: () -> Unit,
    dismissButton: () -> Unit
) {
    AlertDialog(
        title = {
            Text(text = title)
        },
        text = {
            Text(text = message)
        },
        confirmButton = {
            TextButton(onClick = confirmButton) {
                Text("Aceptar")
            }
        },
        dismissButton = {
            TextButton(onClick = dismissButton) {
                Text("Cancelar")
            }
        },
        onDismissRequest = dismissButton
    )
}
🔑 Parámetros de la función:
  • title: Título personalizado del diálogo
  • message: Mensaje personalizado
  • confirmButton: Lambda que se ejecuta al aceptar
  • dismissButton: Lambda que se ejecuta al cancelar o cerrar

Cómo usar la función reutilizable:

var mostrarDialogo by rememberSaveable { mutableStateOf(false) }

Button(onClick = { mostrarDialogo = true }) {
    Text("Eliminar cuenta")
}

if (mostrarDialogo) {
    AlertDialogUi(
        title = "Eliminar cuenta",
        message = "¿Estás seguro de eliminar tu cuenta? Esta acción no se puede deshacer.",
        confirmButton = {
            // Aquí ejecutarías la lógica de eliminación
            mostrarDialogo = false
        },
        dismissButton = {
            mostrarDialogo = false
        }
    )
}
✅ Ventajas de la función reutilizable:
  • Código más limpio y mantenible
  • Fácil de usar en múltiples pantallas
  • Título y mensaje personalizables
  • Lógica de confirmación flexible

💼 Casos de Uso Comunes

🗑️ Eliminar datos

AlertDialogUi(
  title = "Eliminar",
  message = "¿Eliminar?"
  ...
)

🚪 Cerrar sesión

AlertDialogUi(
  title = "Cerrar sesión",
  message = "¿Salir?"
  ...
)

💾 Guardar cambios

AlertDialogUi(
  title = "Cambios sin guardar",
  message = "¿Guardar?"
  ...
)

📤 Salir de la app

AlertDialogUi(
  title = "Salir",
  message = "¿Cerrar app?"
  ...
)

🔄 Flujo Completo del AlertDialog

1 Estado inicial: mostrarDialogo = false

El diálogo está oculto, solo se ve el botón

2 Usuario presiona el botón

Se ejecuta onClick que cambia el estado a true

3 Compose detecta el cambio de estado

La UI se recompone y evalúa la condición if (mostrarDialogo)

4 AlertDialog aparece en pantalla

Se muestra sobre el contenido actual, bloqueando la interacción con el fondo

5 Usuario interactúa con el diálogo

Puede: Presionar "Aceptar", "Cancelar", tocar fuera o presionar atrás

6 Estado vuelve a false

El diálogo se cierra y desaparece de la pantalla

💎 Mejores Prácticas

✅ Haz esto:
  • Usa títulos claros y concisos
  • Mensajes que expliquen claramente la acción
  • Botones con verbos de acción ("Eliminar", "Guardar", "Salir")
  • Siempre implementa onDismissRequest
  • Usa colores apropiados para acciones destructivas
❌ Evita esto:
  • Títulos genéricos como "Atención" o "Aviso"
  • Mensajes largos que requieran scroll
  • Múltiples diálogos apilados
  • Olvidar cambiar el estado en todos los callbacks
  • Usar diálogos para información no crítica

💪 Ejercicio Propuesto

Crea una lista de tareas con confirmación de eliminación:

1 Crea una lista de tareas

Usa LazyColumn para mostrar una lista de tareas con un botón de eliminar en cada item

2 Muestra AlertDialog antes de eliminar

Al presionar eliminar, muestra un diálogo pidiendo confirmación con el nombre de la tarea

3 Implementa la eliminación

Solo elimina la tarea si el usuario confirma en el diálogo

🎯 Bonus:

Agrega un segundo diálogo que aparezca después de eliminar diciendo "Tarea eliminada correctamente" con un solo botón de "Aceptar".

📝 Resumen

✅ Has aprendido:
  • Qué es un AlertDialog y cuándo usarlo
  • Controlar la visibilidad con variables de estado
  • Usar los parámetros obligatorios: confirmButton y onDismissRequest
  • Implementar botones de confirmación y cancelación
  • Crear funciones composables reutilizables
  • Manejar los tres casos de cierre del diálogo
🔑 Puntos clave:
  • El estado controla cuándo mostrar/ocultar el diálogo
  • Siempre cambia el estado a false en confirmButton, dismissButton y onDismissRequest
  • Los diálogos son útiles para acciones destructivas o importantes
  • Mantén los mensajes claros y concisos

📋 Código Completo

Ejemplo Básico:

@Composable
fun DialogExample() {
    var mostrarDialogo by rememberSaveable { mutableStateOf(false) }
    
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Button(onClick = { mostrarDialogo = true }) {
            Text("Mostrar Diálogo")
        }
        
        if (mostrarDialogo) {
            AlertDialog(
                title = { Text("Confirmación") },
                text = { Text("¿Deseas continuar con esta acción?") },
                confirmButton = {
                    TextButton(onClick = { mostrarDialogo = false }) {
                        Text("Aceptar")
                    }
                },
                dismissButton = {
                    TextButton(onClick = { mostrarDialogo = false }) {
                        Text("Cancelar")
                    }
                },
                onDismissRequest = { mostrarDialogo = false }
            )
        }
    }
}

Con Función Reutilizable:

@Composable
fun AlertDialogUi(
    title: String,
    message: String,
    confirmButton: () -> Unit,
    dismissButton: () -> Unit
) {
    AlertDialog(
        title = { Text(text = title) },
        text = { Text(text = message) },
        confirmButton = {
            TextButton(onClick = confirmButton) {
                Text("Aceptar")
            }
        },
        dismissButton = {
            TextButton(onClick = dismissButton) {
                Text("Cancelar")
            }
        },
        onDismissRequest = dismissButton
    )
}

// Uso:
@Composable
fun MyScreen() {
    var mostrarDialogo by rememberSaveable { mutableStateOf(false) }
    
    Button(onClick = { mostrarDialogo = true }) {
        Text("Eliminar cuenta")
    }
    
    if (mostrarDialogo) {
        AlertDialogUi(
            title = "Eliminar cuenta",
            message = "Esta acción no se puede deshacer. ¿Continuar?",
            confirmButton = {
                // Lógica de eliminación aquí
                mostrarDialogo = false
            },
            dismissButton = {
                mostrarDialogo = false
            }
        )
    }
}