更新:Flutter的推荐方法(截至2022年12月20日)…
要显示一个小吃店,你应该使用:
ScaffoldMessenger
从我们读到的文件中
脚手架中的SnackBar API现在由Scaffold messenger处理,其中一个在MaterialApp的上下文中默认是可用的
因此,现在使用ScaffoldMessenger,你将能够编写像这样的代码
Scaffold(
key: scaffoldKey,
body: GestureDetector(
onTap: () {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: const Text('snack'),
duration: const Duration(seconds: 1),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
));
},
child: const Text('SHOW SNACK'),
),
);
现在,在文档中我们可以看到
When presenting a SnackBar during a transition, the SnackBar will complete a Hero animation, moving smoothly to the next page.
The ScaffoldMessenger creates a scope in which all descendant Scaffolds register to receive SnackBars, which is how they persist across these transitions. When using the root ScaffoldMessenger provided by the MaterialApp, all descendant Scaffolds receive SnackBars, unless a new ScaffoldMessenger scope is created further down the tree. By instantiating your own ScaffoldMessenger, you can control which Scaffolds receive SnackBars, and which do not based on the context of your application.
原来的答案
在Flutter文档中,您遇到的这种行为甚至被称为“棘手的情况”。
如何修复
你可以从这里发布的其他答案中看到,这个问题以不同的方式修复。例如,我引用的这篇文档通过使用Builder来解决这个问题
一个内部的BuildContext,这样onPressed方法就可以用Scaffold.of()引用脚手架。
因此,从Scaffold调用showSnackBar的方法如下
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Demo')),
body: Builder(
builder: (BuildContext innerContext) {
return FlatButton(
child: Text('BUTTON'),
onPressed: () {
Scaffold.of(innerContext).showSnackBar(SnackBar(
content: Text('Hello.')
));
}
);
}
)
);
}
现在给好奇的读者一些细节
我自己发现,通过简单地(Android Studio)将光标设置在一段代码上(Flutter类,方法等),并按ctrl+B,就可以显示该特定部分的文档,来探索Flutter文档是非常有指导意义的。
您所面临的特定问题在BuildContext的文档中提到,可以在其中阅读
每个小部件都有自己的BuildContext,它成为[…]返回的小部件的父部件。构建函数。
因此,这意味着在我们的案例中,当创建Scaffold小部件时,上下文将是它的父部件(!)。此外,脚手架的文件。Of表示它会返回
该类最近的[Scaffold]实例的状态,它包含给定的上下文。
但是在我们的例子中,上下文还没有包含脚手架(它还没有被构建)。这就是建造者开始行动的地方!
文档再一次为我们提供了启示。我们可以读到
一个柏拉图式的小部件,它调用一个闭包来获取它的子小部件。
嘿,等一下,什么!?好吧,我承认:这并没有多大帮助……但这足以说明(遵循另一个SO线程)
Builder类的目的只是构建和返回子部件。
现在一切都清楚了!通过在Scaffold中调用Builder,我们正在构建脚手架,以便能够获得它自己的上下文,并且武装了这个innerContext,我们最终可以调用Scaffold.of(innerContext)
下面是上面代码的注释版本
@override
Widget build(BuildContext context) {
// here, Scaffold.of(context) returns null
return Scaffold(
appBar: AppBar(title: Text('Demo')),
body: Builder(
builder: (BuildContext innerContext) {
return FlatButton(
child: Text('BUTTON'),
onPressed: () {
// here, Scaffold.of(innerContext) returns the locally created Scaffold
Scaffold.of(innerContext).showSnackBar(SnackBar(
content: Text('Hello.')
));
}
);
}
)
);
}