在 Flutter 中显示 SnackBar
Display SnackBar in Flutter
我想在 Flutter 的有状态小部件中显示一个简单的SnackBar
。我的应用程序使用名为 MyHomePage
.
的有状态小部件创建 MaterialApp
的新实例
我尝试在 showSnackBar()
方法中显示 SnackBar。但它失败了 The method showSnackBar was called on null
.
这段代码有什么问题?
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
showInSnackBar("Some text");
}
@override
Widget build(BuildContext context) {
return new Padding(
key: _scaffoldKey,
padding: const EdgeInsets.all(16.0),
child: new Text("Simple Text")
);
}
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(value)
));
}
}
解决方案:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(body: new MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
showInSnackBar("Some text");
return new Padding(
padding: const EdgeInsets.all(16.0),
child: new Scaffold(
body: new Text("Simple Text")
)
);
}
void showInSnackBar(String value) {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text(value)
));
}
}
initState
在 build
之前被调用 我猜 _scaffoldKey.currentState
在调用时还没有初始化。
我不知道你能不能从 initState
得到一个 ScaffoldState
。如果您更改代码,您可以使用 build
方法显示小吃栏:
Scaffold.of(context).showSnackBar(SnackBar(Text(value)));
存在三个问题。第一个是您在任何地方都没有脚手架,而脚手架小部件是知道如何显示小吃店的小部件。第二个是你有一把抓住脚手架的钥匙,但你把它放在了一个 Padding 上(而 Paddings 对小吃店一无所知)。第三个是您在与其关联的小部件有机会初始化之前使用了密钥,因为在构建之前调用了 initState。
最简单的解决方案是将 MyApp 小部件中的 home
行更改为:
home: new Scaffold(body: new MyHomePage()),
...然后删除所有提及的 _scaffoldKey
并在您当前有 _scaffoldKey.currentState
.
的地方使用 Scaffold.of(context)
在我的例子中,我有这样的代码(在 class 状态)
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text(value)));
}
但我没有设置脚手架的密钥。
所以当我添加 key: _scaffoldKey
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
body: new SafeArea(
snackbar 开始工作:)
有一种更好、更简洁的方法可以在 flutter 中显示 Snackbar。我发现它很难并分享,所以它可能对其他人有帮助。
无需更改您的主要应用程序部分
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'MyApp',
theme: new ThemeData(
primarySwatch: Colors.orange),
home: new MainPage());
}
}
页面状态代码会发生变化。
我们知道 Flutter 提供 Scaffold.of(context).showSnackBar
。但是,上下文应该是脚手架的后代上下文,而不是包含脚手架的上下文。为了避免出错,我们需要为Scaffold的主体使用一个BuildContext,并将其存储在一个变量中,如下所示。
class MainPageState extends State<MainPage> {
BuildContext scaffoldContext;
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: const Text(APP_TITLE),
),
body: new Builder(builder: (BuildContext context) {
scaffoldContext = context;
return new Center(
child: new Text('Hello World', style: new TextStyle(fontSize: 32.0)),
);
}));
}
void createSnackBar(String message) {
final snackBar = new SnackBar(content: new Text(message),
backgroundColor: Colors.red);
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
Scaffold.of(scaffoldContext).showSnackBar(snackBar);
}
}
现在,您可以从任何地方调用此函数,它会显示 Snackbar。例如,我用它来显示 Internet 连接消息。
以防有人想在 initState()
上初始化 Snackbar
(换句话说,当页面加载到这里时,我的解决方案就是)。另外,我假设您已经准备好 _scaffoldKey
。
void initState() {
super.initState();
Future.delayed(Duration(seconds: 1)).then(
(_) => _displaySnackbar
);
}
// Display Snackbar
void get _displaySnackbar {
_scaffoldKey.currentState.showSnackBar(SnackBar(
duration: Duration(minutes: 1),
content: Text('Your snackbar message')
));
}
要在 initState() 上初始化 Snackbar,您可以在构建布局后执行函数。
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Your message here..")));}
Scaffold.of(context).showSnackBar(
SnackBar(content: Text("Thanks for using snackbar",
textAlign: TextAlign.center, style: TextStyle(fontSize: 16.0, fontWeight:
FontWeight.bold),), duration: Duration(seconds: 2), backgroundColor: Colors.red,)
);
你可以使用这个:
final _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
),
}
}
然后
在onPressed()
可以添加这个代码
_scaffoldKey.currentState.showSnackBar(
new SnackBar(
content: new Text('Hello this is snackbar!')
)
);
您可以通过三个简单的步骤完成此操作。
确保您有脚手架的钥匙。您可以通过编写以下代码来创建它:
final _scaffoldKey = GlobalKey<ScaffoldState>();
2.Now 你必须在你的脚手架中提到这个键,通过在脚手架中写下下面的行:
key:_scaffoldKey,
现在你可以通过写来显示snackbar:
final snackBar=SnackBar(
content: Text('Your password has been changed successfully'),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
最好的方法是创建一个 PageWrapper,您可以包装所有页面以获取 Scaffold 小部件的上下文并避免再次遇到这些错误。
这是页面包装器的示例:
import 'package:flutter/material.dart';
class PageWrapper extends StatelessWidget {
Widget page;
WPage(this.page);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: page
);
}
}
然后您可以将所有页面包装在 main.dart 中,如下所示:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
initialRoute: '/login',
routes: {
'/login': (context) => PageWrapper(Login()),
'/home': (context) => PageWrapper(Home())
}
));
现在您可以在任何页面的任意位置调用 Scaffold.of(context)
。
参考:https://noobieprogrammer.blogspot.com/2020/06/how-to-create-error-alert-or-popup.html
或观看视频版本(5 分钟长):https://youtu.be/u9KoFtu0HEY
如果您在一个没有直接 return Scaffold(...)
小部件的小部件中,您可以这样做:
Scaffold.of(context).showSnackBar(SnackBar(content: Text("Hello from snackbar")));
不需要创建额外的 Scaffold 小部件,因为 showSnackBar()
方法需要一个,您可以重复使用。
ScaffoldState
现已弃用。使用 ScaffoldMessengerState
.
通常有两种显示 SnackBar
的方法,使用 ScaffoldMessenger
。
直接方式:
@override
Widget build(BuildContext context) {
return Scaffold(
body: ElevatedButton(
onPressed: () {
var snackBar = SnackBar(content: Text('Hello World'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
child: Text('Show SnackBar'),
),
);
}
使用GlobalKey
。
final _globalKey = GlobalKey<ScaffoldMessengerState>();
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
key: _globalKey,
child: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
var snackBar = SnackBar(content: Text('Hello World'));
_globalKey.currentState.showSnackBar(snackBar);
},
child: Text('Show SnackBar'),
),
),
),
);
}
ScaffoldState 现已弃用。使用 ScaffoldMessengerState。
上述所有解决方案都很棒,但由于现在已弃用,您应该以这种方式使用它。
var snackBar = SnackBar(content: Text('Hello World'));
ScaffoldMessenger.of(_scaffoldKey.currentContext)
.showSnackBar(snackBar );
Scaffold.Of(context)
已弃用,因为它显示了小吃店。
使用新方式:
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
在空安全版本中--
class _testPageState extends State<testPage> {
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SizedBox(
child: Scaffold(
key: _scaffoldKey,
body: Center(
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: () {
final snackBar = SnackBar(content: Text('Your Text'));
_scaffoldKey.currentState!.showSnackBar(snackBar);
},
child: Text("Show SB"),
)
)
)
)
);
}
}
在Flutter中显示SnackBar
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Please Enter Valid Data'),
backgroundColor: Colors.red,
));
示例:
if(value.isNotEmpty && value != null){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Validated Successfully'),
backgroundColor: Colors.green,
));
}else{
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Please Enter Valid Data'),
backgroundColor: Colors.red,
));
}
我想在 Flutter 的有状态小部件中显示一个简单的SnackBar
。我的应用程序使用名为 MyHomePage
.
MaterialApp
的新实例
我尝试在 showSnackBar()
方法中显示 SnackBar。但它失败了 The method showSnackBar was called on null
.
这段代码有什么问题?
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
showInSnackBar("Some text");
}
@override
Widget build(BuildContext context) {
return new Padding(
key: _scaffoldKey,
padding: const EdgeInsets.all(16.0),
child: new Text("Simple Text")
);
}
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(value)
));
}
}
解决方案:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(body: new MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
showInSnackBar("Some text");
return new Padding(
padding: const EdgeInsets.all(16.0),
child: new Scaffold(
body: new Text("Simple Text")
)
);
}
void showInSnackBar(String value) {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text(value)
));
}
}
initState
在 build
之前被调用 我猜 _scaffoldKey.currentState
在调用时还没有初始化。
我不知道你能不能从 initState
得到一个 ScaffoldState
。如果您更改代码,您可以使用 build
方法显示小吃栏:
Scaffold.of(context).showSnackBar(SnackBar(Text(value)));
存在三个问题。第一个是您在任何地方都没有脚手架,而脚手架小部件是知道如何显示小吃店的小部件。第二个是你有一把抓住脚手架的钥匙,但你把它放在了一个 Padding 上(而 Paddings 对小吃店一无所知)。第三个是您在与其关联的小部件有机会初始化之前使用了密钥,因为在构建之前调用了 initState。
最简单的解决方案是将 MyApp 小部件中的 home
行更改为:
home: new Scaffold(body: new MyHomePage()),
...然后删除所有提及的 _scaffoldKey
并在您当前有 _scaffoldKey.currentState
.
Scaffold.of(context)
在我的例子中,我有这样的代码(在 class 状态)
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text(value)));
}
但我没有设置脚手架的密钥。 所以当我添加 key: _scaffoldKey
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
body: new SafeArea(
snackbar 开始工作:)
有一种更好、更简洁的方法可以在 flutter 中显示 Snackbar。我发现它很难并分享,所以它可能对其他人有帮助。
无需更改您的主要应用程序部分
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'MyApp',
theme: new ThemeData(
primarySwatch: Colors.orange),
home: new MainPage());
}
}
页面状态代码会发生变化。
我们知道 Flutter 提供 Scaffold.of(context).showSnackBar
。但是,上下文应该是脚手架的后代上下文,而不是包含脚手架的上下文。为了避免出错,我们需要为Scaffold的主体使用一个BuildContext,并将其存储在一个变量中,如下所示。
class MainPageState extends State<MainPage> {
BuildContext scaffoldContext;
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: const Text(APP_TITLE),
),
body: new Builder(builder: (BuildContext context) {
scaffoldContext = context;
return new Center(
child: new Text('Hello World', style: new TextStyle(fontSize: 32.0)),
);
}));
}
void createSnackBar(String message) {
final snackBar = new SnackBar(content: new Text(message),
backgroundColor: Colors.red);
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
Scaffold.of(scaffoldContext).showSnackBar(snackBar);
}
}
现在,您可以从任何地方调用此函数,它会显示 Snackbar。例如,我用它来显示 Internet 连接消息。
以防有人想在 initState()
上初始化 Snackbar
(换句话说,当页面加载到这里时,我的解决方案就是)。另外,我假设您已经准备好 _scaffoldKey
。
void initState() {
super.initState();
Future.delayed(Duration(seconds: 1)).then(
(_) => _displaySnackbar
);
}
// Display Snackbar
void get _displaySnackbar {
_scaffoldKey.currentState.showSnackBar(SnackBar(
duration: Duration(minutes: 1),
content: Text('Your snackbar message')
));
}
要在 initState() 上初始化 Snackbar,您可以在构建布局后执行函数。
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Your message here..")));}
Scaffold.of(context).showSnackBar(
SnackBar(content: Text("Thanks for using snackbar",
textAlign: TextAlign.center, style: TextStyle(fontSize: 16.0, fontWeight:
FontWeight.bold),), duration: Duration(seconds: 2), backgroundColor: Colors.red,)
);
你可以使用这个:
final _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
),
}
}
然后
在onPressed()
可以添加这个代码
_scaffoldKey.currentState.showSnackBar(
new SnackBar(
content: new Text('Hello this is snackbar!')
)
);
您可以通过三个简单的步骤完成此操作。
确保您有脚手架的钥匙。您可以通过编写以下代码来创建它:
final _scaffoldKey = GlobalKey<ScaffoldState>();
2.Now 你必须在你的脚手架中提到这个键,通过在脚手架中写下下面的行:
key:_scaffoldKey,
现在你可以通过写来显示snackbar:
final snackBar=SnackBar( content: Text('Your password has been changed successfully'), ); _scaffoldKey.currentState.showSnackBar(snackBar);
最好的方法是创建一个 PageWrapper,您可以包装所有页面以获取 Scaffold 小部件的上下文并避免再次遇到这些错误。
这是页面包装器的示例:
import 'package:flutter/material.dart';
class PageWrapper extends StatelessWidget {
Widget page;
WPage(this.page);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: page
);
}
}
然后您可以将所有页面包装在 main.dart 中,如下所示:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
initialRoute: '/login',
routes: {
'/login': (context) => PageWrapper(Login()),
'/home': (context) => PageWrapper(Home())
}
));
现在您可以在任何页面的任意位置调用 Scaffold.of(context)
。
参考:https://noobieprogrammer.blogspot.com/2020/06/how-to-create-error-alert-or-popup.html
或观看视频版本(5 分钟长):https://youtu.be/u9KoFtu0HEY
如果您在一个没有直接 return Scaffold(...)
小部件的小部件中,您可以这样做:
Scaffold.of(context).showSnackBar(SnackBar(content: Text("Hello from snackbar")));
不需要创建额外的 Scaffold 小部件,因为 showSnackBar()
方法需要一个,您可以重复使用。
ScaffoldState
现已弃用。使用 ScaffoldMessengerState
.
通常有两种显示 SnackBar
的方法,使用 ScaffoldMessenger
。
直接方式:
@override Widget build(BuildContext context) { return Scaffold( body: ElevatedButton( onPressed: () { var snackBar = SnackBar(content: Text('Hello World')); ScaffoldMessenger.of(context).showSnackBar(snackBar); }, child: Text('Show SnackBar'), ), ); }
使用
GlobalKey
。final _globalKey = GlobalKey<ScaffoldMessengerState>(); @override Widget build(BuildContext context) { return ScaffoldMessenger( key: _globalKey, child: Scaffold( body: Center( child: ElevatedButton( onPressed: () { var snackBar = SnackBar(content: Text('Hello World')); _globalKey.currentState.showSnackBar(snackBar); }, child: Text('Show SnackBar'), ), ), ), ); }
ScaffoldState 现已弃用。使用 ScaffoldMessengerState。
上述所有解决方案都很棒,但由于现在已弃用,您应该以这种方式使用它。
var snackBar = SnackBar(content: Text('Hello World'));
ScaffoldMessenger.of(_scaffoldKey.currentContext)
.showSnackBar(snackBar );
Scaffold.Of(context)
已弃用,因为它显示了小吃店。
使用新方式:
final snackBar = SnackBar(content: Text('Yay! A SnackBar!'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
在空安全版本中--
class _testPageState extends State<testPage> {
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SizedBox(
child: Scaffold(
key: _scaffoldKey,
body: Center(
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onPressed: () {
final snackBar = SnackBar(content: Text('Your Text'));
_scaffoldKey.currentState!.showSnackBar(snackBar);
},
child: Text("Show SB"),
)
)
)
)
);
}
}
在Flutter中显示SnackBar
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Please Enter Valid Data'),
backgroundColor: Colors.red,
));
示例:
if(value.isNotEmpty && value != null){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Validated Successfully'),
backgroundColor: Colors.green,
));
}else{
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Please Enter Valid Data'),
backgroundColor: Colors.red,
));
}