Snackbar是Android 5.0新特性——Material Design中的一个控件,用来代替Toast,Snackbar与Toast的主要区别是:Snackbar可以滑动退出,也可以处理用户交互(点击)事件。
在Flutter开发时,对于提示性信息,有人已经想到写一个插件去调用Android原生的Toast,且不说还要兼容IOS,这种反历史潮流的行为,一方面伤害了移动端的UI统一体验,另一方面对于主打Material Design设计的Flutter来说,也是不符合Google开发这套框架的初衷的。
言归正传,我们重点看看怎么使用这个控件, SnackBar是通过Scaffold的showSnackBar方法来显示的。所以要显示一个SnackBar,要先拿到Scaffold。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: new Text(
"登录",
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
elevation: 0.0,
centerTitle: true,
),
body: new RaisedButton(
onPressed: () async {
login(context);
},
color: Color(0xFFE60012),
child: new Padding(
padding: const EdgeInsets.all(13.0),
child: new Text(
"登录",
style: new TextStyle(
color: Colors.white,
fontSize: 18.0,
fontWeight: FontWeight.bold),
)),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
));
}
首先创建一个SnackBar,再通过Scaffold的方法来显示。
void login(BuildContext context) {
if (userPhone.isEmpty) {
final snackBar = new SnackBar(content: new Text("手机号不能为空"));
Scaffold.of(context).showSnackBar(snackBar);
return;
}
}
有时候,我们可能会想在显示的提示信息上添加一些操作。例如提示用户删除了一条消息,可以在提示信息上添加一个撤消的按钮,要达到这个效果,我们可以在SnackBar上添加一个操作按钮。
final snackBar = new SnackBar(
content: new Text('删除信息'),
action: new SnackBarAction(
label: '撤消',
onPressed: () {
// do something to undo
}),
);
当BuildContext在Scaffold之前时,调用Scaffold.of(context)会报错。这时可以通过Builder Widget来解决,代码如下:
body: new Builder(builder: (BuildContext context) {
return Container(
margin: new EdgeInsets.all(15.0),
child: ListView(
children: <Widget>[
SizedBox(
height: 30,
),
new Center(
child: new Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
new Image.asset("images/pair_guide_icon.png"),
new Column(children: <Widget>[
SizedBox(
height: 30,
),
new Text(
"长按3秒“播放/暂停”键开启蓝牙",
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
]),
]),
),
new SizedBox(
height: 30.0,
),
new RaisedButton(
onPressed: isBtnEnabled
? () {
searchDevice(context);
}
: null,
color: isBtnEnabled ? Color(0xFFE60012) : Color(0xFFEBEBEB),
child: new Padding(
padding: const EdgeInsets.all(13.0),
child: new Text(pairBtnStatus,
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
color: isBtnEnabled ? Colors.white : Colors.black,
))),
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
),
new SizedBox(
height: 10.0,
),
new Center(
child: FlatButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0)),
child: new Text("需要帮助"),
onPressed: () async {
String callPhone = "tel:4008123456";
if (await canLaunch(callPhone)) {
await launch(callPhone);
} else {
throw 'Could not launch $callPhone';
}
},
),
),
],
));
}),
拿到context后,就可以尽情使用SnackBar了:
void searchDevice(BuildContext context) {
BleManager.getInstance().setOnBleState((BluetoothState state) {
if (state != BluetoothState.on) {
final snackBar = new SnackBar(content: new Text("请先打开蓝牙"));
Scaffold.of(context).showSnackBar(snackBar);
} else {
BleManager.getInstance().startScan();
}
});
}