Comme vous pouvez le voir, mon bouton est à l'intérieur du corps de Scaffold. Mais j'obtiens cette exception:
Scaffold.of () appelé avec un contexte qui ne contient pas de 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);
}
ÉDITER:
J'ai trouvé une autre solution à ce problème. Si nous donnons à Scaffold une clé qui est GlobalKey, nous pouvons afficher le SnackBar comme suit sans avoir besoin d'envelopper notre corps avec le widget Builder. Le widget qui renvoie Scaffold doit être un widget avec état:
_scaffoldKey.currentState.showSnackBar(snackbar);
Réponses:
Cette exception se produit car vous utilisez
context
le widget qui a instanciéScaffold
. Pas celuicontext
d'un enfant deScaffold
.Vous pouvez résoudre ce problème en utilisant simplement un contexte différent:
Notez que pendant que nous utilisons
Builder
ici, ce n'est pas le seul moyen d'obtenir un fichier différentBuildContext
.Il est également possible d'extraire le sous-arbre dans un autre
Widget
(généralement en utilisantextract widget
refactor)la source
onPressed
vous avez passéRaisedButton
n'est pas une fonction. Changer pour() => _displaySnackBar(context)
Vous pouvez utiliser un fichier
GlobalKey
. Le seul inconvénient est que l'utilisation de GlobalKey n'est peut-être pas le moyen le plus efficace de le faire.Une bonne chose à ce sujet est que vous pouvez également passer cette clé à d'autres classes de widgets personnalisés qui ne contiennent aucun échafaudage. Voir ( ici )
la source
_scaffoldKey
est privé en raison du trait de soulignement principal. Mais même si ce n'était pas le cas, il est à l'intérieur de laHomePage
classe et donc indisponible sans instancier une nouvelle page d'accueil quelque part dans l'arborescence, créant apparemment une référence circulaire.GlobalKey<ScaffoldState>
propriété, éditez le constructeur du widget avec l'échafaudage pour définir la propriété clé du singleton, puis dans l'arborescence du widget enfant, nous pouvons appeler quelque chose commemySingleton.instance.key.currentState.showSnackBar()
...Deux façons de résoudre ce problème
1) Utilisation du widget Builder
2) Utilisation de GlobalKey
la source
Vérifiez cela dans la documentation de la méthode:
Vous pouvez vérifier la description de la de la méthode docs
la source
Un moyen simple de résoudre ce problème sera de créer une clé pour votre échafaudage comme cette finale avec le code suivant:
Première:
GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState> ();
Scecond: attribuez la clé à votre échafaudage
key: _scaffoldKey
Troisièmement: appelez le Snackbar en utilisant
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
la source
Le comportement même que vous rencontrez est même qualifié de "cas délicat" dans la documentation Flutter .
Comment réparer
Le problème est résolu de différentes manières, comme vous pouvez le voir dans d'autres réponses publiées ici. Par exemple, la documentation à laquelle je fais référence résout le problème en utilisant un
Builder
qui créeAinsi, un moyen d'appeler
showSnackBar
depuis Scaffold seraitMaintenant quelques détails pour le lecteur curieux
J'ai moi-même trouvé assez instructif d'explorer la documentation Flutter simplement ( Android Studio ) en plaçant le curseur sur un morceau de code ( classe Flutter , méthode, etc.) et en appuyant sur ctrl + B pour afficher la documentation de ce morceau spécifique.
Le problème particulier auquel vous êtes confronté est mentionné dans le docu de BuildContext , où peut être lu
Donc, cela signifie que dans notre cas, le contexte sera le parent de notre widget Scaffold lors de sa création (!). De plus, le docu pour Scaffold.of dit qu'il renvoie
Mais dans notre cas, le contexte ne renferme pas (encore) un échafaudage (il n'a pas encore été construit). C'est là que Builder entre en action!
Une fois de plus, le docu nous éclaire. Là on peut lire
Hé, attendez un instant, quoi!? Ok, j'avoue: ça n'aide pas beaucoup ... Mais il suffit de dire (suite à un autre fil SO ) que
Alors maintenant, tout devient clair! En appelant Builder à l' intérieur de Scaffold, nous construisons le Scaffold afin de pouvoir obtenir son propre contexte, et armés de ce innerContext, nous pouvons enfin appeler Scaffold.of (innerContext)
Une version annotée du code ci-dessus suit
la source
Je ne prendrais pas la peine d'utiliser le snack par défaut, car vous pouvez importer un package flushbar, ce qui permet une plus grande personnalisation:
https://pub.dev/packages/flushbar
Par exemple:
la source
Une solution plus efficace consiste à diviser votre fonction de construction en plusieurs widgets. Cela introduit un `` nouveau contexte '', à partir duquel vous pouvez obtenir Scaffold
la source
Extrayez votre widget bouton qui affichera le snackbar.
la source
ici, nous utilisons un constructeur pour envelopper un autre widget où nous avons besoin d'un snack
la source