Как вы можете видеть, моя кнопка находится внутри корпуса Скаффолда. Но я получаю это исключение:
Scaffold.of () вызывается с контекстом, который не содержит 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);
}
РЕДАКТИРОВАТЬ:
Я нашел другое решение этой проблемы. Если мы дадим Scaffold ключ, который называется GlobalKey, мы можем отобразить SnackBar следующим образом без необходимости оборачивать наше тело виджетом Builder. Хотя виджет, который возвращает Scaffold, должен быть виджетом Stateful.
_scaffoldKey.currentState.showSnackBar(snackbar);
Ответы:
Это исключение происходит потому, что вы используете
context
созданный экземпляр виджетаScaffold
. Неcontext
дитяScaffold
.Вы можете решить эту проблему, просто используя другой контекст:
Обратите внимание, что хотя мы используем
Builder
здесь, это не единственный способ получить другоеBuildContext
.Также возможно извлечь поддерево в другое
Widget
(обычно используяextract widget
рефакторинг)источник
onPressed
Вы прошли , чтобыRaisedButton
это не функция. Измените это на() => _displaySnackBar(context)
Вы можете использовать
GlobalKey
. Единственным недостатком является то, что использование GlobalKey может быть не самым эффективным способом сделать это.Хорошо, что вы также можете передать этот ключ другим классам пользовательских виджетов, которые не содержат никаких скаффолдов. Смотрите ( здесь )
источник
_scaffoldKey
является частной из-за ведущих подчеркивания. Но даже если это не так, он находится внутриHomePage
класса и поэтому недоступен, не создавая новую страницу HomePage где-то вниз по дереву, создавая циклическую ссылку.GlobalKey<ScaffoldState>
свойством, отредактируйте конструктор виджета с помощью скаффолда, чтобы установить свойство ключа синглтона, затем в дереве дочернего виджета мы можем вызвать что-то вродеmySingleton.instance.key.currentState.showSnackBar()
...Два способа решить эту проблему
1) Использование виджета Builder
2) Использование GlobalKey
источник
Проверьте это из документации метода:
Вы можете проверить описание из метода документов
источник
Простым способом решения этой проблемы будет создание ключа для вашего скаффолда, как этот финал, с помощью следующего кода:
Первый:
GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState> ();
Scecond: назначьте ключ вашему эшафоту
key: _scaffoldKey
В-третьих: вызвать Снэк-бар
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
источник
Само поведение, которое вы испытываете, даже упоминается как «сложный случай» в документации Flutter .
Как исправить
Проблема решается по-разному, как вы можете видеть из других ответов, размещенных здесь. Например, часть документации я см решает проблему, используя
Builder
который создаетТаким образом, способ звонить
showSnackBar
с эшафот будетТеперь немного подробностей для любознательного читателя
Я сам нашел весьма поучительным изучить документацию Flutter , просто ( Android Studio ) установив курсор на фрагмент кода ( класс Flutter , метод и т. Д.) И нажав ctrl + B, чтобы показать документацию для этого конкретного фрагмента.
Конкретная проблема, с которой вы сталкиваетесь, упоминается в документе для BuildContext , где можно прочитать
Таким образом, это означает, что в нашем случае контекст будет родителем нашего виджета Scaffold при его создании (!). Далее, документ для Scaffold.of говорит, что он возвращает
Но в нашем случае контекст не включает (пока) Скаффолд (он еще не построен). Там, где Строитель вступает в действие!
Еще раз, документ освещает нас. Там мы можем прочитать
Эй, подожди минутку, что? Хорошо, я признаю: это не очень помогает ... Но достаточно сказать (следуя другому такому потоку ), что
Так что теперь все становится ясно! Вызывая Builder внутри Scaffold, мы строим Scaffold для того, чтобы иметь возможность получить его собственный контекст, и, вооружившись этим innerContext, мы можем наконец вызвать Scaffold.of (innerContext).
Аннотированная версия приведенного выше кода следует
источник
Я бы не стал использовать снэк-бар по умолчанию, потому что вы можете импортировать пакет флешбаров, который обеспечивает большую настраиваемость:
https://pub.dev/packages/flushbar
Например:
источник
Более эффективное решение - разделить вашу функцию сборки на несколько виджетов. Это вводит «новый контекст», из которого вы можете получить скаффолд
источник
Извлеките свой виджет кнопки, который будет отображать снэк-бар.
источник
здесь мы используем конструктор для переноса в другой виджет, где нам нужна закусочная
источник