Scaffold.of(), вызванный контекстом, который не содержит леса
Как видите, моя кнопка находится внутри тела Леса. Но я получаю это исключение:
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, должен быть видоизмененным.
_scaffoldKey.currentState.showSnackBar(snackbar);
Ответы
Ответ 1
Это исключение происходит потому, что вы используете context
виджета, который создает экземпляр Scaffold
. Не context
ребенка Scaffold
.
Вы можете решить эту проблему, просто используя другой контекст:
Scaffold(
appBar: AppBar(
title: Text('SnackBar Playground'),
),
body: Builder(
builder: (context) =>
Center(
child: RaisedButton(
color: Colors.pink,
textColor: Colors.white,
onPressed: () => _displaySnackBar(context),
child: Text('Display SnackBar'),
),
),
),
);
Обратите внимание, что хотя мы используем здесь Builder
, это не единственный способ получить другой BuildContext
.
Также возможно извлечь поддерево в другой Widget
(обычно с использованием рефактора extract widget
)
Ответ 2
Вы можете использовать GlobalKey
. Единственным недостатком является то, что использование GlobalKey может быть не самым эффективным способом сделать это.
Хорошо, что вы также можете передать этот ключ другим классам пользовательских виджетов, которые не содержат никаких скаффолдов. Смотрите (здесь)
class HomePage extends StatelessWidget {
final _scaffoldKey = GlobalKey<ScaffoldState>(); \\ new line
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey, \\ new line
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?'));
_scaffoldKey.currentState.showSnackBar(snackBar); \\ edited line
}
Ответ 3
Проверьте это из документации метода:
Когда Scaffold действительно создается в той же функции сборки, контекстный аргумент функции сборки не может быть использован для поиска Эшафот (так как он "выше" возвращаемого виджета). В таком В следующих случаях для построения новая область с BuildContext, который находится "под" скаффолдом:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Demo')
),
body: Builder(
// Create an inner BuildContext so that the onPressed methods
// can refer to the Scaffold with Scaffold.of().
builder: (BuildContext context) {
return Center(
child: RaisedButton(
child: Text('SHOW A SNACKBAR'),
onPressed: () {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text('Hello!'),
));
},
),
);
},
),
);
}
Вы можете проверить описание в методе документации.
Ответ 4
Простым способом решения этой проблемы будет создание ключа для вашего скаффолда, например, финального, со следующим кодом:
Первый: GlobalKey<ScaffoldState>() _scaffoldKey = GlobalKey<ScaffoldState>
();
Scecond: назначьте ключ на ваш эшафот key: _scaffoldKey
В-третьих: вызвать Снэк-бар, используя
_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));
Ответ 5
Хорошие новости!
Нам больше не нужно оборачивать наш виджет в Builder
или использовать вещи GlobalKey
, чтобы предоставить виджету context
Scaffold
. С приходом Flutter к стабильной версии 1.0 команда работала над этим. Теперь мы можем напрямую использовать в нашем классе Stateful
State
Scaffold.of(context).showSnackBar(SnackBar(content: Text("Hi there")));
Ответ 6
Есть два способа решения этой проблемы
1) Использование виджета Builder
Scaffold(
appBar: AppBar(
title: Text('My Profile'),
),
body: Builder(
builder: (ctx) => RaisedButton(
textColor: Colors.red,
child: Text('Submit'),
onPressed: () => Scaffold.of(ctx).showSnackBar(SnackBar(content: Text('Profile Save'),
),
),
),
);
2) Использование GlobalKey
class HomePage extends StatelessWidget {
final globalKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: globalKey,
appBar: AppBar(
title: Text('My Profile'),
),
body: RaisedButton(
textColor: Colors.red,
child: Text('Submit'),
onPressed: showSnackbar(context),
),
),
);
}
}
void showSnackbar(BuildContext context) {
final snackBar = SnackBar(content: Text('Profile saved'));
globalKey.currentState.showSnackBar(snackBar);
}