Cuando empecé a trabajar con feedback visual en Flutter, descubrí que ScaffoldMessenger era exactamente lo que necesitaba para mostrar confirmaciones rápidas, casi como los “flash messages” de las apps web. Ese mismo patrón que uso cuando elimino un registro o confirmo un pago lo resolví de forma limpia y consistente con esta herramienta.
En esta guía te cuento qué es, cómo funciona, cuándo conviene usarlo y te dejo tres ejemplos prácticos de SnackBars personalizados, incluido uno avanzado con Stack, iconos y diseño completo.
Nos quedamos en que logramos implementar el efecto de pellizcar en Flutter, vamos con otro tema.
Qué es ScaffoldMessenger y por qué reemplaza al antiguo Scaffold.of(context)
Si alguna vez usaste Scaffold.of(context).showSnackBar(), seguro te topaste con el famoso error del contexto no válido. También me pasó al principio: no podía mostrar un mensaje justo después de navegar o al ejecutar una acción asincrónica.
Ahí es donde entra ScaffoldMessenger: un widget global capaz de gestionar SnackBars sin depender del contexto inmediato.
Diferencia entre ambos enfoques
- Scaffold.of(context) → Depende del árbol de widgets. Si el context no tiene acceso al Scaffold, falla.
- ScaffoldMessenger.of(context) → Se coloca en la raíz (MaterialApp) y gestiona mensajes desde cualquier parte.
Ventajas reales al trabajar con SnackBars
- Más estable al trabajar con navegación.
- Ideal para mostrar mensajes después de operaciones como eliminar, actualizar o pagar (a mí me funciona justamente para esos casos).
- Permite SnackBars más complejos, animados o con layouts personalizados.
Cuándo usar ScaffoldMessenger: casos reales del día a día
Usar ScaffoldMessenger tiene sentido cuando necesitas confirmar acciones importantes o dar feedback inmediato sin interrumpir la navegación.
Mensajes tipo “flash” después de acciones críticas
En mis proyectos lo uso cuando:
- elimino un registro,
- realizo un pago,
- confirmo un cambio en un formulario,
- notifico al usuario que algo sí ocurrió.
Ese tipo de comunicación rápida levanta mucho la experiencia del usuario.
Confirmaciones (pagos, eliminaciones, ediciones)
Algo clave es que el mensaje se muestre incluso si acabas de navegar. Ahí ScaffoldMessenger es un salvavidas; nunca falla por tener un contexto “viejo”.
Ejemplos prácticos de ScaffoldMessenger en Flutter
Exploraremos los mensajes de error de Flash en Flutter personalizando un mensaje de tipo ScaffoldMessenger.
Vamos a implementar la siguiente estructura:
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/logo.png',height: 300,width: 350,),
Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.cyan,
),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text(
¡Este nombre de usuario no se encuentra!)));
},
child: const Text('Show Flash Error Message')),
),
],
),Dentro de ElevatedButton, agregaremos el estilo y la función onPressed. En esta función, crearemos un método SnackBar() simple. En este método, agregaremos contenido que es igual al texto '¡Este nombre de usuario no se encuentra! Por favor, inténtelo de nuevo más tarde.
Ahora, esta vez todos son iguales pero solo cambios en SnackBar(). Dentro de SnackBar(), agregaremos un comportamiento igual a SnackBarBehavior.floating y contenido igual al widget Container. En este widget, agregaremos relleno, altura y el BoxDecoration con el color azul y el radio del borde circular.
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.cyan,
),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar( SnackBar(
behavior: SnackBarBehavior.floating,
content: Container(
padding: const EdgeInsets.all(8),
height: 70,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: const Center(
child: Text(
'This Username is not found! Please try again later'),
),
),
));
},
child: const Text('Show Flash Error Message')),Por último, pero no menos importante, esta vez haremos otros cambios en SnackBar() en ElevatedButton(). En el interior, agregaremos un color de fondo transparente, el comportamiento es igual a SnackBarBehavior.floating, la elevación es 0 y el contenido es igual al widget Stack().
Dentro del widget, agregaremos alineación en el centro, clipBehavior en nulo. También agregaremos un widget de Row. En este widget, agregaremos una Columna. En esta columna, agregaremos dos widgets de texto.
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.cyan,
),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.transparent,
behavior: SnackBarBehavior.floating,
elevation: 0,
content: Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Container(
padding: const EdgeInsets.all(8),
height: 70,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: Row(
children: [
const SizedBox(
width: 48,
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Oops Error!',
style: TextStyle(
fontSize: 18, color: Colors.white),
),
Text(
'This Username is not found! Please try again later',
style: TextStyle(
fontSize: 14, color: Colors.white),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
Positioned(
bottom: 25,
left: 20,
child: ClipRRect(
child: Stack(
children: [
Icon(
Icons.circle,
color: Colors.red.shade200,
size: 17,
)
],
),
)),
Positioned(
top: -20,
left: 5,
child: Stack(
alignment: Alignment.center,
children: [
Container(
height: 30,
width: 30,
decoration: const BoxDecoration(
color: Colors.red,
borderRadius:
BorderRadius.all(Radius.circular(15)),
),
),
const Positioned(
top: 5,
child: Icon(
Icons.clear_outlined,
color: Colors.white,
size: 20,
))
],
)),
],
),
));
},
child: const Text('Show Flash Error Message')),Luego, agregaremos un widget Posicionado. En este widget, agregaremos la parte inferior es 25 y la izquierda es 20. En este elemento secundario, agregaremos ClipRRect y dentro agregaremos un ícono de círculo. Además, crearemos un widget posicionado más. En este widget, agregaremos un ícono claro.
SnackBar simple (error o confirmación)
Este es el ejemplo más limpio y directo:
ElevatedButton(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('¡Este nombre de usuario no se encuentra!'),
),
);
},
child: const Text('Mostrar mensaje'),
);Ideal cuando solo quieres confirmar algo rápido, como cuando yo valido datos antes de procesar un pago.
SnackBar flotante personalizado
Aquí ya agregamos diseño, paddings y una caja con borde redondeado:
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
behavior: SnackBarBehavior.floating,
content: Container(
padding: const EdgeInsets.all(8),
height: 70,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: const Center(
child: Text('This Username is not found! Please try again later'),
),
),
),
);Uso algo parecido cuando quiero que el mensaje “flote” sin tapar controles importantes.
SnackBar avanzado (Stack + íconos + layout completo)
Este es el ejemplo que uso cuando quiero un “flash message” con presencia visual, especialmente al confirmar eliminaciones o errores críticos:
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Colors.transparent,
behavior: SnackBarBehavior.floating,
elevation: 0,
content: Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
Container(
padding: const EdgeInsets.all(8),
height: 70,
decoration: const BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: Row(
children: [
const SizedBox(width: 48),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Oops Error!',
style: TextStyle(fontSize: 18, color: Colors.white),
),
Text(
'This Username is not found! Please try again later',
style: TextStyle(fontSize: 14, color: Colors.white),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
),
),
Positioned(
bottom: 25,
left: 20,
child: ClipRRect(
child: Icon(
Icons.circle,
color: Colors.redAccent,
size: 17,
),
),
),
Positioned(
top: -20,
left: 5,
child: Stack(
alignment: Alignment.center,
children: [
Container(
height: 30,
width: 30,
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
),
const Positioned(
top: 5,
child: Icon(
Icons.clear_outlined,
color: Colors.white,
size: 20,
),
),
],
),
),
],
),
),
);Perfecto para pantallas donde quieres comunicar algo fuerte sin usar un diálogo modal.
Personalización profunda del SnackBar
- Cambiar colores, bordes y layouts
- El SnackBar es casi como un mini-card: puedes ajustar color, padding, sombra, borde, iconos, textos y hasta animaciones.
- Añadir íconos, acciones y comportamientos
- Yo suelo añadir:
- iconos de éxito/error,
- acciones como “Deshacer”,
- variantes flotantes, transparentes o con sombra cero.
Errores comunes al usar ScaffoldMessenger (y cómo evitarlos)
- Usar context incorrectos
- El clásico error donde el SnackBar no aparece. La regla es simple: usa siempre el context que cuelga de un Scaffold con acceso al MaterialApp.
- SnackBars que no se muestran
- Sucede cuando navegas justo antes de llamar a showSnackBar.
Con ScaffoldMessenger esto ya no pasa.
- Sucede cuando navegas justo antes de llamar a showSnackBar.
- Mensajes duplicados o acumulados
- Ojo: si no cierras el SnackBar anterior, puede quedar en cola.
Puedes usar hideCurrentSnackBar() para evitarlo.
- Ojo: si no cierras el SnackBar anterior, puede quedar en cola.
FAQs rápidas sobre ScaffoldMessenger
- ¿Puede reemplazar completamente a Scaffold.of(context)?
- Sí, y debería.
- ¿Sirve solo para SnackBars?
- No; también gestiona información visual que afecta al Scaffold.
- ¿Dónde debo colocarlo?
- Generalmente alrededor de tu MaterialApp.
Conclusión
ScaffoldMessenger es una herramienta clave para mostrar mensajes rápidos, confiables y con diseño moderno. En mi caso es esencial cuando realizo operaciones como eliminar registros, confirmar pagos o mostrar errores críticos, porque asegura que el mensaje se vea siempre, sin importar dónde esté el usuario en la navegación.
Si diseñas UI con buen feedback, este widget es imprescindible.
El siguiente paso, consiste en que conozcas como implementar una lista de elementos en Flutter con el ListView.
Acepto recibir anuncios de interes sobre este Blog.
Domina ScaffoldMessenger en Flutter para mostrar mensajes SnackBar fiables y evitar errores de contexto. Aprende a crear notificaciones personalizadas para confirmaciones, errores o pagos con ejemplos de código, desde un mensaje simple hasta un diseño avanzado con iconos y Stack.