Como você pode ver, meu botão está dentro do corpo do andaime. Mas eu recebo esta exceção:
Scaffold.of () chamado com um contexto que não contém um 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:
Encontrei outra solução para esse problema. Se dermos ao Scaffold uma chave que é GlobalKey, podemos exibir a SnackBar da seguinte forma, sem precisar envolver nosso corpo com o widget Builder. O widget que retorna o Scaffold deve ser um widget Stateful:
_scaffoldKey.currentState.showSnackBar(snackbar);
Respostas:
Essa exceção acontece porque você está usando
context
o widget que foi instanciadoScaffold
. Não écontext
de um filho deScaffold
.Você pode resolver isso usando apenas um contexto diferente:
Observe que enquanto estivermos usando
Builder
aqui, essa não é a única maneira de obter um método diferente.BuildContext
.Também é possível extrair a subárvore em uma diferente
Widget
(geralmente usandoextract widget
refator)fonte
onPressed
você passouRaisedButton
não é uma função. Altere para() => _displaySnackBar(context)
Você pode usar a
GlobalKey
. A única desvantagem é que o uso da GlobalKey pode não ser a maneira mais eficiente de fazer isso.Uma coisa boa disso é que você também pode passar essa chave para outra classe de widgets personalizados que não contêm nenhum andaime. Veja ( aqui )
fonte
_scaffoldKey
é privado devido ao sublinhado principal. Mas, mesmo que não estivesse, está dentro daHomePage
classe e, portanto, não está disponível sem instanciar uma nova HomePage em algum lugar da árvore, aparentemente criando uma referência circular.GlobalKey<ScaffoldState>
propriedade, edite o construtor do Widget com o andaime para definir a propriedade chave do singleton e, na árvore do widget filho, podemos chamar algo comomySingleton.instance.key.currentState.showSnackBar()
...Duas maneiras de resolver esse problema
1) Usando o widget Construtor
2) Usando GlobalKey
fonte
Verifique isso na documentação do método:
Você pode verificar a descrição nos documentos do método
fonte
Uma maneira simples de resolver esse problema será criar uma chave para o seu andaime, como esta final, com o seguinte código:
Primeiro:
GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState> ();
Scecond: atribua a chave ao seu andaime
key: _scaffoldKey
Terceiro: Ligue para a Snackbar usando
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
fonte
O próprio comportamento que você está enfrentando é referido como um "caso complicado" na documentação do Flutter .
Como consertar
O problema foi corrigido de maneiras diferentes, como você pode ver em outras respostas postadas aqui. Por exemplo, a documentação a que me refiro resolve o problema usando um
Builder
que criaAssim, uma maneira de ligar
showSnackBar
do andaime seriaAgora, alguns detalhes para o leitor curioso
Eu mesmo achei bastante instrutivo explorar a documentação do Flutter simplesmente ( Android Studio ) configurando o cursor em um trecho de código ( classe Flutter , método, etc.) e pressionando ctrl + B para exibir a documentação dessa peça específica.
O problema específico que você está enfrentando é mencionado no documento do BuildContext , onde pode ser lido
Portanto, isso significa que, no nosso caso, o contexto será o pai do nosso widget de andaime quando ele for criado (!). Além disso, o documento para Scaffold.of diz que ele retorna
Mas, no nosso caso, o contexto ainda não inclui um andaime (ele ainda não foi construído). É aí que o Builder entra em ação!
Mais uma vez, o docu nos ilumina. Lá podemos ler
Ei, espere um momento, o que !? Ok, admito: isso não está ajudando muito ... Mas basta dizer (seguindo outro tópico do SO ) que
Então agora tudo fica claro! Ao chamar o Builder dentro do Scaffold , estamos construindo o Scaffold para obter seu próprio contexto e, armados com o innerContext , podemos finalmente chamar Scaffold.of (innerContext)
Uma versão anotada do código acima segue
fonte
Eu não me incomodaria em usar a snackbar padrão, porque você pode importar um pacote flushbar, o que permite uma maior personalização:
https://pub.dev/packages/flushbar
Por exemplo:
fonte
Uma solução mais eficiente é dividir sua função de compilação em vários widgets. Isso introduz um 'novo contexto', do qual você pode obter o Andaime
fonte
Extraia o widget de botão que exibirá a lanchonete.
fonte
aqui usamos um construtor para envolver outro widget onde precisamos da lanchonete
fonte