SnackBars administrados por el ScaffoldMessenger
Los SnackBars ahora son gestionados por el ScaffoldMessenger, y persisten a través de las rutas.
Resumen
#La API de SnackBar dentro del Scaffold ahora es manejada por el
ScaffoldMessenger, uno de los cuales está
disponible por defecto dentro del contexto de un MaterialApp.
Contexto
#Antes de este cambio, los SnackBars se mostraban llamando
al Scaffold dentro del BuildContext actual.
Al llamar a Scaffold.of(context).showSnackBar,
el Scaffold actual animaba un SnackBar a la vista.
Esto solo se aplicaba al Scaffold actual,
y no persistía a través de las rutas si estas cambiaban
durante la presentación del SnackBar.
Esto también provocaba errores si se llamaba a showSnackBar
durante la ejecución de un evento asíncrono, y el BuildContext se invalidaba
debido al cambio de ruta y al desecho (disposed) del Scaffold.
El ScaffoldMessenger ahora maneja los SnackBars para que
persistan a través de las rutas y siempre se muestren en el Scaffold actual.
Por defecto, se incluye un ScaffoldMessenger raíz en el MaterialApp,
pero puedes crear tu propio alcance controlado para el ScaffoldMessenger
para controlar mejor qué Scaffolds reciben tus SnackBars.
Descripción del cambio
#El enfoque anterior requería del Scaffold para mostrar un SnackBar.
Scaffold(
key: scaffoldKey,
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(SnackBar(
content: const Text('snack'),
duration: const Duration(seconds: 1),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
));
},
child: const Text('SHOW SNACK'),
);
},
)
);
El nuevo enfoque requiere del ScaffoldMessenger para mostrar
el SnackBar. En este caso, ya no se requiere el Builder
para proporcionar un nuevo alcance con un BuildContext que
esté "debajo" del Scaffold.
Scaffold(
key: scaffoldKey,
body: GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('snack'),
duration: const Duration(seconds: 1),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
));
},
child: const Text('SHOW SNACK'),
),
);
Al presentar un SnackBar durante una transición,
el SnackBar completa una animación Hero,
moviéndose suavemente a la página siguiente.
El ScaffoldMessenger crea un alcance en el que todos los
Scaffolds descendientes se registran para recibir SnackBars,
que es como persisten a través de estas transiciones.
Al usar el ScaffoldMessenger raíz provisto por el
MaterialApp, todos los Scaffolds descendientes reciben SnackBars,
a menos que se cree un nuevo alcance de ScaffoldMessenger más abajo en el árbol.
Al instanciar tu propio ScaffoldMessenger,
puedes controlar qué Scaffolds reciben SnackBars y cuáles no,
según el contexto de tu aplicación.
El método debugCheckHasScaffoldMessenger está disponible para asegurar
que un contexto dado tenga un ancestro ScaffoldMessenger.
Intentar presentar un SnackBar sin un ancestro ScaffoldMessenger
presente da como resultado una aserción como la siguiente:
No ScaffoldMessenger widget found.
Scaffold widgets require a ScaffoldMessenger widget ancestor.
Typically, the ScaffoldMessenger widget is introduced by the MaterialApp
at the top of your application widget tree.
Guía de migración
#Código antes de la migración:
// The ScaffoldState of the current context was used for managing SnackBars.
Scaffold.of(context).showSnackBar(mySnackBar);
Scaffold.of(context).hideCurrentSnackBar(mySnackBar);
Scaffold.of(context).removeCurrentSnackBar(mySnackBar);
// If a Scaffold.key is specified, the ScaffoldState can be directly
// accessed without first obtaining it from a BuildContext via
// Scaffold.of. From the key, use the GlobalKey.currentState
// getter. This was previously used to manage SnackBars.
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
Scaffold(
key: scaffoldKey,
body: ...,
);
scaffoldKey.currentState.showSnackBar(mySnackBar);
scaffoldKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldKey.currentState.removeCurrentSnackBar(mySnackBar);
Código después de la migración:
// The ScaffoldMessengerState of the current context is used for managing SnackBars.
ScaffoldMessenger.of(context).showSnackBar(mySnackBar);
ScaffoldMessenger.of(context).hideCurrentSnackBar(mySnackBar);
ScaffoldMessenger.of(context).removeCurrentSnackBar(mySnackBar);
// If a ScaffoldMessenger.key is specified, the ScaffoldMessengerState can be directly
// accessed without first obtaining it from a BuildContext via
// ScaffoldMessenger.of. From the key, use the GlobalKey.currentState
// getter. This is used to manage SnackBars.
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
ScaffoldMessenger(
key: scaffoldMessengerKey,
child: ...
)
scaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);
// The root ScaffoldMessenger can also be accessed by providing a key to
// MaterialApp.scaffoldMessengerKey. This way, the ScaffoldMessengerState can be directly accessed
// without first obtaining it from a BuildContext via ScaffoldMessenger.of. From the key, use
// the GlobalKey.currentState getter.
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp(
scaffoldMessengerKey: rootScaffoldMessengerKey,
home: ...
)
rootScaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);
Timeline
#Introducido en la versión: 1.23.0-13.0.pre
En el lanzamiento estable: 2.0.0
Referencias
#Documentación de la API:
Issues relevantes:
PRs relevantes:
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.