Como puede ver, mi botón está dentro del cuerpo de Scaffold. Pero me sale esta excepción:
Scaffold.of () llamado con un contexto que no contiene un Scaffold.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SnackBar Playground'),
),
body: Center(
child: RaisedButton(
color: Colors.pink,
textColor: Colors.white,
onPressed: _displaySnackBar(context),
child: Text('Display SnackBar'),
),
),
);
}
}
_displaySnackBar(BuildContext context) {
final snackBar = SnackBar(content: Text('Are you talkin\' to me?'));
Scaffold.of(context).showSnackBar(snackBar);
}
EDITAR:
Encontré otra solución a este problema. Si le damos a Scaffold una clave que es GlobalKey, podemos mostrar SnackBar de la siguiente manera sin necesidad de envolver nuestro cuerpo con el widget Builder. Sin embargo, el widget que devuelve Scaffold debería ser Stateful widget .:
_scaffoldKey.currentState.showSnackBar(snackbar);
Respuestas:
Esta excepción ocurre porque está utilizando
context
el widget que instanciaScaffold
. No elcontext
de un hijo deScaffold
.Puede resolver esto simplemente usando un contexto diferente:
Tenga en cuenta que mientras estamos usando
Builder
aquí, esta no es la única forma de obtener una diferenteBuildContext
.También es posible extraer el subárbol en un diferente
Widget
(generalmente usandoextract widget
refactor)fuente
onPressed
que pasasteRaisedButton
no es una función. Cámbielo a() => _displaySnackBar(context)
Puedes usar a
GlobalKey
. El único inconveniente es que usar GlobalKey podría no ser la forma más eficiente de hacerlo.Lo bueno de esto es que también puede pasar esta clave a otra clase de widgets personalizados que no contienen ningún andamio. Ver ( aquí )
fuente
_scaffoldKey
es privado debido al guión bajo destacado. Pero incluso si no fuera así, está dentro de laHomePage
clase y, por lo tanto, no está disponible sin crear una instancia de una nueva página de inicio en algún lugar del árbol, aparentemente creando una referencia circular.GlobalKey<ScaffoldState>
propiedad, editar el constructor del Widget con el andamio para establecer la propiedad clave del singleton, luego en el árbol del widget secundario podemos llamar algo así comomySingleton.instance.key.currentState.showSnackBar()
...Dos formas de resolver este problema
1) Uso del widget de generador
2) Usando GlobalKey
fuente
Verifique esto en la documentación del método:
Puede consultar la descripción de los documentos del método
fuente
Una manera simple de resolver este problema será crear una clave para su andamio como esta final con el siguiente código:
Primero:
GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState> ();
Scecond: asigna la llave a tu andamio
key: _scaffoldKey
Tercero: llame al Snackbar usando
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
fuente
El mismo comportamiento que está experimentando incluso se conoce como un "caso complicado" en la documentación de Flutter .
Como arreglar
El problema se soluciona de diferentes maneras, como puede ver en otras respuestas publicadas aquí. Por ejemplo, la pieza de documentación a la que me refiero resuelve el problema mediante el uso de un
Builder
que creaPor lo tanto, una forma de llamar
showSnackBar
desde Scaffold seríaAhora algunos detalles para el lector curioso
Yo mismo encontré bastante instructivo para explorar la documentación de Flutter simplemente ( Android Studio ) colocando el cursor en una pieza de código ( clase de Flutter , método, etc.) y presionando ctrl + B para mostrar la documentación de esa pieza específica.
El problema particular que enfrenta se menciona en el documento de BuildContext , donde se puede leer
Entonces, esto significa que, en nuestro caso, el contexto será el padre de nuestro widget Scaffold cuando se cree (!). Además, el docu para Scaffold.of dice que regresa
Pero en nuestro caso, el contexto no encierra (todavía) un Andamio (aún no se ha construido). ¡Ahí es donde entra en acción Builder !
Una vez más, el docu nos ilumina. Allí podemos leer
Oye, espera un momento, ¿qué? Ok, lo admito: eso no está ayudando mucho ... Pero es suficiente decir (siguiendo otro hilo SO ) que
¡Así que ahora todo queda claro! Al llamar a Builder dentro de Scaffold , estamos construyendo el Scaffold para poder obtener su propio contexto, y armados con ese contexto interno , finalmente podemos llamar a Scaffold.of (innerContext)
Sigue una versión anotada del código anterior
fuente
No me molestaría en usar la barra de aperitivos predeterminada, porque puede importar un paquete de barra de descarga, que permite una mayor personalización:
https://pub.dev/packages/flushbar
Por ejemplo:
fuente
Una solución más eficiente es dividir su función de compilación en varios widgets. Esto introduce un 'nuevo contexto', desde el cual puede obtener Scaffold
fuente
Extraiga su widget de botón que mostrará snackbar.
fuente
aquí usamos un generador para envolver en otro widget donde necesitamos snackbar
fuente