Flutter 的 Display SnackBar

我想显示一个 简单的 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)
));
}
}
144253 次浏览

initStatebuild之前被调用,我猜 _scaffoldKey.currentState在被调用时还没有被初始化。

我不知道你能不能从 initState中得到 ScaffoldState。如果您更改了代码,您可以使用以下命令显示来自 build方法的快餐栏:

Scaffold.of(context).showSnackBar(SnackBar(Text(value)));

有三个问题。首先,您在任何地方都没有脚手架,而脚手架小部件知道如何显示快餐吧。第二个问题是,您有一个获取脚手架的密钥,但是您将其放在了 Paddings 上(而 Paddings 并不知道任何关于快餐店的知识)。第三,在与之关联的小部件有机会被初始化之前就使用了密钥,因为 initState 在构建之前就被调用了。

最简单的解决方案是将 MyApp 小部件中的 home行更改为:

home: new Scaffold(body: new MyHomePage()),

... 然后删除所有提到的 _scaffoldKey,而是使用 Scaffold.of(context)的地方,你目前有 _scaffoldKey.currentState

在我的例子中,我有这样的代码(在类状态下)

final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();


void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text(value)));
}

但我没有设置脚手架的钥匙。 因此,当我添加 < strong > key: _ scripoldKey 时

 @override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
body: new SafeArea(

点心吧开始工作:)

有一个更好更干净的方式来显示快餐吧在颤动。我觉得这是一个艰难的过程,所以也许这对其他人也有帮助。

不需要改变你的主应用程序部分

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。但是,上下文应该是脚手架的后代的上下文,而不是包含脚手架的上下文。为了避免错误,我们需要将 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!')
)
);

您可以通过三个简单的步骤来实现这一点。

  1. 确保你有一个脚手架的密钥,你可以通过编写下面的代码来创建它:

    final _scaffoldKey = GlobalKey<ScaffoldState>();
    

2.Now you have to mention this key inside your Scaffold, by writing the below line inside scaffold:

key:_scaffoldKey,
  1. 现在你可以通过写下:

    final snackBar=SnackBar(
    content: Text('Your password has been changed successfully'),
    );
    _scaffoldKey.currentState.showSnackBar(snackBar);
    

最好的方法是创建一个 PageWrapper,您可以包装所有页面以获得 Saffold 小部件的上下文,并避免再次出现这些错误。

下面是页面包装器的一个示例:

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")));

没有必要创建额外的 Saffold 小部件,因为 showSnackBar()方法需要一个,您可以重用它。

现在不推荐使用 ScaffoldState。请使用 ScaffoldMessengerState

使用 ScaffoldMessenger显示 SnackBar通常有两种方法。


  1. 直达方式:

    @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'),
    ),
    );
    }
    

  1. 使用 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'),
    ),
    ),
    ),
    );
    }
    

现在不推荐使用 SaffoldState。请使用 SaffoldMessengerState。

以上所有的解决方案都是令人惊讶的,但是现在已经不再使用它了,你应该这样使用它。

    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);

snackbars

在空安全版本中

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 的 Display 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,
));
}

使用此包零食吧

Customsnackbar: ^ 0.0.1

ShowCustomSnackBar (“ Hello”,10.0,5,Colors.white) ;

ScaffoldMessenger.of(context)
.showSnackBar(new SnackBar(content: Text('SnackBar Message')));


  

我们可以用这个

**

ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text("Enter your phone number"),
),
);

**