ScaffoldMessenger 管理的 SnackBars
摘要
#Scaffold
中的 SnackBar
API 现在由 ScaffoldMessenger
处理,其中一个默认在 MaterialApp
的上下文中可用。
上下文
#在此更改之前,SnackBar
通过调用当前 BuildContext
中的 Scaffold
来显示。通过调用 Scaffold.of(context).showSnackBar
,当前 Scaffold
会将 SnackBar
动画显示出来。这仅适用于当前 Scaffold
,如果在 SnackBar
显示过程中更改了路由,则不会跨路由持续存在。如果在执行异步事件的过程中调用 showSnackBar
,并且 BuildContext
因路由更改和 Scaffold
被释放而失效,也会导致错误。
ScaffoldMessenger
现在处理 SnackBar
,以便跨路由持久化并在当前 Scaffold
上始终显示。默认情况下,根 ScaffoldMessenger
包含在 MaterialApp
中,但您可以为 ScaffoldMessenger
创建自己的受控范围,以进一步控制哪些 Scaffold
接收您的 SnackBar
。
更改说明
#以前的方法调用 Scaffold
来显示 SnackBar
。
Scaffold(
key: scaffoldKey,
body: Builder(
builder: (BuildContext context) {
return GestureDetector(
onTap: () {
Scaffold.of(context).showSnackBar(SnackBar(
content: const Text('snack'),
duration: const Duration(seconds: 1),
action: SnackBarAction(
label: 'ACTION',
onPressed: () { },
),
));
},
child: const Text('SHOW SNACK'),
);
},
)
);
新方法调用 ScaffoldMessenger
来显示 SnackBar
。在这种情况下,不再需要 Builder
来提供一个新的范围,其中包含位于 Scaffold
“下方”的 BuildContext
。
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'),
),
);
在过渡期间显示 SnackBar
时,SnackBar
会完成 Hero
动画,平滑地移动到下一页。
ScaffoldMessenger
创建了一个范围,其中所有后代 Scaffold
都注册以接收 SnackBar
,这就是它们能够跨这些过渡持续存在的方式。当使用 MaterialApp
提供的根 ScaffoldMessenger
时,所有后代 Scaffold
都会接收 SnackBar
,除非在树的更下方创建了一个新的 ScaffoldMessenger
范围。通过实例化您自己的 ScaffoldMessenger
,您可以根据应用程序的上下文控制哪些 Scaffold
接收 SnackBar
,哪些不接收。
debugCheckHasScaffoldMessenger
方法可用于断言给定的上下文是否具有 ScaffoldMessenger
祖先。尝试在没有 ScaffoldMessenger
祖先的情况下显示 SnackBar
会导致断言,例如以下内容
No ScaffoldMessenger widget found.
Scaffold widgets require a ScaffoldMessenger widget ancestor.
Typically, the ScaffoldMessenger widget is introduced by the MaterialApp
at the top of your application widget tree.
迁移指南
#迁移前的代码
// The ScaffoldState of the current context was used for managing SnackBars.
Scaffold.of(context).showSnackBar(mySnackBar);
Scaffold.of(context).hideCurrentSnackBar(mySnackBar);
Scaffold.of(context).removeCurrentSnackBar(mySnackBar);
// If a Scaffold.key is specified, the ScaffoldState can be directly
// accessed without first obtaining it from a BuildContext via
// Scaffold.of. From the key, use the GlobalKey.currentState
// getter. This was previously used to manage SnackBars.
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
Scaffold(
key: scaffoldKey,
body: ...,
);
scaffoldKey.currentState.showSnackBar(mySnackBar);
scaffoldKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldKey.currentState.removeCurrentSnackBar(mySnackBar);
迁移后的代码
// The ScaffoldMessengerState of the current context is used for managing SnackBars.
ScaffoldMessenger.of(context).showSnackBar(mySnackBar);
ScaffoldMessenger.of(context).hideCurrentSnackBar(mySnackBar);
ScaffoldMessenger.of(context).removeCurrentSnackBar(mySnackBar);
// If a ScaffoldMessenger.key is specified, the ScaffoldMessengerState can be directly
// accessed without first obtaining it from a BuildContext via
// ScaffoldMessenger.of. From the key, use the GlobalKey.currentState
// getter. This is used to manage SnackBars.
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
ScaffoldMessenger(
key: scaffoldMessengerKey,
child: ...
)
scaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
scaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);
// The root ScaffoldMessenger can also be accessed by providing a key to
// MaterialApp.scaffoldMessengerKey. This way, the ScaffoldMessengerState can be directly accessed
// without first obtaining it from a BuildContext via ScaffoldMessenger.of. From the key, use
// the GlobalKey.currentState getter.
final GlobalKey<ScaffoldMessengerState> rootScaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
MaterialApp(
scaffoldMessengerKey: rootScaffoldMessengerKey,
home: ...
)
rootScaffoldMessengerKey.currentState.showSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.hideCurrentSnackBar(mySnackBar);
rootScaffoldMessengerKey.currentState.removeCurrentSnackBar(mySnackBar);
时间线
#包含版本:1.23.0-13.0.pre
稳定版:2.0.0
参考文献
#API 文档
相关问题
相关 PR
除非另有说明,否则本网站上的文档反映了 Flutter 的最新稳定版本。页面上次更新于 2024-04-04。 查看源代码 或 报告问题.