Wie Sie sehen können, befindet sich mein Knopf in Scaffolds Körper. Aber ich bekomme diese Ausnahme:
Scaffold.of () wird mit einem Kontext aufgerufen, der kein Scaffold enthält.
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);
}
BEARBEITEN:
Ich habe eine andere Lösung für dieses Problem gefunden. Wenn wir Scaffold einen Schlüssel geben, der GlobalKey ist, können wir die SnackBar wie folgt anzeigen, ohne unseren Körper mit dem Builder-Widget umschließen zu müssen. Das Widget, das Scaffold zurückgibt, sollte jedoch ein Stateful-Widget sein:
_scaffoldKey.currentState.showSnackBar(snackbar);
Antworten:
Diese Ausnahme tritt auf, weil Sie das
context
des instanziierten Widgets verwendenScaffold
. Nicht dascontext
eines Kindes vonScaffold
.Sie können dies lösen, indem Sie einfach einen anderen Kontext verwenden:
Beachten Sie, dass
Builder
dies nicht die einzige Möglichkeit ist, eine andere zu erhalten , während wir hier verwendenBuildContext
.Es ist auch möglich, den Teilbaum in einen anderen zu extrahieren
Widget
(normalerweise mitextract widget
Refactor).quelle
onPressed
Sie übergeben haben,RaisedButton
ist keine Funktion. Ändern Sie es zu() => _displaySnackBar(context)
Sie können eine verwenden
GlobalKey
. Der einzige Nachteil ist, dass die Verwendung von GlobalKey möglicherweise nicht die effizienteste Methode ist.Eine gute Sache dabei ist, dass Sie diesen Schlüssel auch an andere benutzerdefinierte Widgets-Klassen übergeben können, die kein Gerüst enthalten. Siehe ( hier )
quelle
_scaffoldKey
ist aufgrund des führenden Unterstrichs privat. Aber selbst wenn dies nicht derHomePage
Fall wäre , befindet es sich innerhalb der Klasse und ist daher nicht verfügbar, ohne dass irgendwo im Baum eine neue HomePage instanziiert wird, die scheinbar einen Zirkelverweis erstellt.GlobalKey<ScaffoldState>
Eigenschaft, bearbeiten Sie den Konstruktor des Widgets mit dem Gerüst, um die Schlüsseleigenschaft des SingletonsmySingleton.instance.key.currentState.showSnackBar()
Zwei Möglichkeiten, um dieses Problem zu lösen
1) Verwenden des Builder-Widgets
2) Verwenden von GlobalKey
quelle
Überprüfen Sie dies aus der Dokumentation der Methode:
Sie können die Beschreibung von der Prüfung der Methode docs
quelle
Eine einfache Möglichkeit, dieses Problem zu lösen, besteht darin, einen Schlüssel für Ihr Gerüst wie dieses Finale mit dem folgenden Code zu erstellen:
Zuerst:
GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState> ();
Sekunde: Weisen Sie den Schlüssel Ihrem Gerüst zu
key: _scaffoldKey
Drittens: Rufen Sie die Snackbar mit
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
quelle
Das Verhalten, das Sie erleben, wird in der Flutter- Dokumentation sogar als "kniffliger Fall" bezeichnet .
Wie repariert man
Das Problem wird auf verschiedene Arten behoben, wie Sie aus anderen hier veröffentlichten Antworten ersehen können. Zum Beispiel löst die Dokumentation, auf die ich mich beziehe, das Problem durch die Verwendung von a,
Builder
das erstelltEin Weg, um
showSnackBar
von Scaffold aus anzurufen, wäre alsoNun ein Detail für den neugierigen Leser
Ich selbst fand es sehr lehrreich, die Flutter- Dokumentation zu erkunden, indem ich einfach ( Android Studio ) den Cursor auf einen Code ( Flutter- Klasse, Methode usw.) setzte und Strg + B drückte, um die Dokumentation für diesen bestimmten Teil anzuzeigen.
Das spezielle Problem, mit dem Sie konfrontiert sind, wird im Dokument für BuildContext erwähnt , in dem es gelesen werden kann
So bedeutet dies , dass in unserem Fall Zusammenhang wird die Mutter unseres Scaffold - Widget , wenn es erstellt wird (!). Weiter sagt das Dokument für Scaffold.of , dass es zurückkehrt
In unserem Fall enthält der Kontext jedoch (noch) kein Gerüst (es wurde noch nicht erstellt). Hier kommt Builder zum Einsatz!
Wieder einmal beleuchtet uns das Dokument. Dort können wir lesen
Hey, warte einen Moment, was? Ok, ich gebe zu: das hilft nicht viel ... Aber es reicht zu sagen (nach einem anderen SO-Thread ), dass
Jetzt wird alles klar! Indem wir Builder in Scaffold aufrufen , erstellen wir das Scaffold, um seinen eigenen Kontext zu erhalten, und mit diesem inneren Kontext können wir schließlich Scaffold.of (innerContext) aufrufen.
Eine kommentierte Version des obigen Codes folgt
quelle
Ich würde die Standard-Snackbar nicht verwenden, da Sie ein Flushbar-Paket importieren können, das eine bessere Anpassbarkeit ermöglicht:
https://pub.dev/packages/flushbar
Beispielsweise:
quelle
Eine effizientere Lösung besteht darin, Ihre Build-Funktion in mehrere Widgets aufzuteilen. Dies führt einen "neuen Kontext" ein, aus dem Sie Scaffold erhalten können
quelle
Extrahieren Sie Ihr Schaltflächen-Widget, das die Snackbar anzeigt.
quelle
Hier verwenden wir einen Builder, um ein anderes Widget einzuschließen, in dem wir eine Snackbar benötigen
quelle