做原生開發(fā)的時候,我們都知道要想讓一個app做的活靈活現(xiàn),與用戶交互時有更棒的體驗,各種樣式美輪美奐的對話框跟提示是必不可少的,F(xiàn)lutter在設(shè)計對話框的時候充分考慮到了在UI上的體驗,幫助我們設(shè)計了一整套的基于material design風格的對話框以及輕量級的用于提示的widget。

看完上面的效果圖,讀者是不是也覺得這一套UI設(shè)計給人以很棒的體驗,下面我們就逐一介紹下上圖中出現(xiàn)的常用于提示的widget。
輕量級提示
這里提到的輕量級提示指的是在提示出現(xiàn)的過程中不會打斷用戶當前正在進行中的操作,只是在UI上有一小段時間的提示,隔一段時間之后提示內(nèi)容自動消失,例如原生Android的Toast、SnackBar一樣,并不會像Dialog一樣出現(xiàn)之后用戶必須停止正在進行的操作去完成Dialog引發(fā)的邏輯操作之后才能繼續(xù)在dialog出現(xiàn)之前的操作。
1.Tooltip
Tooltip支持用戶傳入任意一個child作為顯示的Widget,并且在用戶長按Widget時,會在上方或者下方出現(xiàn)類似Toast的提示,隔一段時間自動消失,由于使用起來比較簡單,我就在代碼注釋里講解就不展開贅述了。
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
home: new MyApp(),
));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Tooltips"),
),
body: Center(
child: Tooltip(
message: "顯示提示內(nèi)容",//提示的內(nèi)容
height: 60.0,//Tooltip的高度
verticalOffset: 50.0,//具體內(nèi)部child Widget豎直方向的距離,
preferBelow:false,//是否顯示在下面
padding: EdgeInsets.all(20.0),//padding
child: Icon(
Icons.android,
size: 50.0,
color: Colors.green,
)),
),
);
}
}
效果圖

2.SnackBar
SnackBar無論是用法還是功能使用幾乎都跟原生Android一樣 ,唯一有一點需要留意的是在Scaffold.of(context).showSnackBar()中傳遞的context必須不能是Scaffold下面的Context
原因解釋
因為Scaffold.of() 方法需要從Widget樹中去找到Scaffold的Context,所以如果直接在Scaffold中使用showSnackBar,需要在外城包括上Builder Widget,這個Builder不做任何的其他操作,只不過把Widget樹往下移了一層而已,這里也是很多初學者照著網(wǎng)上的Demo寫完之后怎么寫彈不出來SnackBar的原因,所以這里特此說明一下。
來看下SnackBar的效果圖,你會發(fā)現(xiàn)跟原生Android如出一轍。

樣例代碼
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("SnackBar"),
),
body: new Center(
child: new Builder(builder: (BuildContext context) {
return new RaisedButton(
onPressed: () {
//值得注意的是這個context必須不能是Scaffold節(jié)點下的context,因為Scaffold.of()
// 方法需要從Widget樹中去找到Scaffold的Context,所以如果直接在Scaffold中使用showSnackBar,
// 需要在外城包括上Builder Widget,這個Builder不做任何的其他操作,只不過把Widget樹往下移了一層而已。
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text("SanckBar is Showing "),
action: new SnackBarAction(
label: "撤銷",
onPressed: () {
print("點擊撤回---------------");
}),
));
},
child: new Text("SnackBar提示"),
color: Colors.cyan,
highlightColor: Colors.lightBlueAccent,
disabledColor: Colors.lightBlueAccent,
);
}),
),
);
}
}
//const SnackBar({
//Key key,
//@required this.content,//內(nèi)容
//this.backgroundColor,//背景
//this.action,//其他操作
//this.duration: _kSnackBarDisplayDuration,//顯示時長
//this.animation,//進出動畫
//})
非輕量級操作
上面介紹了Tooltip跟SnackBar,在介紹此二者的時候筆者也提到它們定位為輕量級的提示W(wǎng)idget,那對應(yīng)的就會有非輕量級的提示組件,意思就是在此類提示出現(xiàn)的過程中,會打斷用戶正在進行的操作,強制用戶處處理對話框上的邏輯之后才能回過頭來繼續(xù)原有的用戶操作,例如AlertDialog、BottomSheetDialog等,接下來筆者就帶大家一起體驗一下這類提示操作的用法。
Flutter中要求開發(fā)者通過
showDialog(context,child),來喚起各種不同類型的dialog顯示,context為上下文參數(shù),child為要顯示的對話框類型,例如,SimpleDialog、AlertDialog、AboutDialog、BottomSheetDialog等都需要借助showDialog來喚起。
1.SimpleDialog
SimpleDialog跟它的名字一樣,它就是一個簡單的對話框,開發(fā)者只需傳入title跟child就可以使用它,其中child是一個Widget數(shù)組,用戶可以根據(jù)業(yè)務(wù)需求傳入任意的Widget,然后借助showDialog喚起即可。
效果圖

樣例代碼
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("SimpleDialog"),
),
body: new Center(
child: new RaisedButton(
onPressed: () {
showDialog(
context: context,
child: new SimpleDialog(
title: new Text("標題"),
contentPadding: const EdgeInsets.all(10.0),
children: <Widget>[ //SimpleDialog內(nèi)可指定多個children
new Text("文字內(nèi)容1"),
new ListTile(
leading: new Icon(Icons.android),
title: new Text("android"),
),
new Text("文字內(nèi)容2"),
new Text("文字內(nèi)容3"),
new Text("文字內(nèi)容4"),
],
));
},
child: new Text("Dialog出來"),
color: Colors.blue,
highlightColor: Colors.lightBlueAccent,
disabledColor: Colors.lightBlueAccent),
),
);
}
}
2.AlertDialog
AlertDialog其實就是simpleDialog的封裝,更加方便開發(fā)者使用,只不過在SimpleDialog的基礎(chǔ)上新增了action操作而已,用戶可以定制具體類似,“取消”、“確定”等一切可能存在dialog上的邏輯處理。其余沒有什么需要特別強調(diào)的知識點,也是跟simpledialog一樣,需要借助showDialog喚起,使用起來比較簡單,直接從代碼里說明了。
樣例代碼
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("AlertDialog"),
),
body: new Center(
child: new Builder(builder: (BuildContext context) {
return new RaisedButton(
onPressed: () {
showDialog(
context: context,
child: new AlertDialog(
title: new Text("標題"),
content: new Text("內(nèi)容區(qū)域"),
actions: <Widget>[
new FlatButton(
onPressed: () {
Navigator.of(context);
},
child: new Text("確定")),
new FlatButton(
onPressed: () {
print("點擊取消------");
},
child: new Text("取消")),
],
));
},
color: Colors.lightBlueAccent,
child: new Icon(Icons.phone),
);
}),
),
);
}
}
效果圖

文章開頭的效果圖上提到的aboutDialog跟alertDialog類似,同樣也是封裝了simpleDialog,讀者可自行閱讀嘗試具體用法,我就不在此詳細解說了,下面我想說一下BottomSheetDialog跟ModalBottomSheetDialog。
3.BottomSheetDialog、ModalBottomSheetDialog
BottomSheetDialog、ModalBottomSheetDialog同樣也是需要借助showDialog喚起,就跟它名字一樣,這兩種dialog是從屏幕下方向上彈出的,不同的是BottomSheetDialog默認會鋪滿全屏顯示,而ModalBottomSheetDialog半屏顯示,二者都支持隨用戶手指拖動上下移動。
方法簽名
1.
showBottomSheet(context,child)上下文參數(shù),Widget數(shù)組
2.showModalBottomSheet(context,child)上下文參數(shù),Widget數(shù)組
來一起體驗一下這倆東西怎么使用

樣例代碼
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(home: new MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("BottomSheet"),
),
body: new Column(
children: <Widget>[
new Builder(builder: (BuildContext context){
return new RaisedButton(
onPressed: () {
showBottomSheet(
context: context,
builder: (BuildContext context) {
return new Container(
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Column(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.chat),
title: new Text("對話框列表1"),
),
new ListTile(
leading: new Icon(Icons.help),
title: new Text("對話框列表2"),
),
new ListTile(
leading: new Icon(Icons.settings),
title: new Text("對話框列表3"),
),
new ListTile(
leading: new Icon(Icons.more),
title: new Text("對話框列表4"),
),
],
),
),
);
});
},
child: new Text("BottomSheet"),
);
}),
//showModalBottomSheet與BottomSheet的區(qū)別是 BottomSheet充滿屏幕,ModalBottomSheet半屏
new RaisedButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return new Container(
child: new Padding(
padding: const EdgeInsets.all(10.0),
child: new Column(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.chat),
title: new Text("對話框列表1"),
),
new ListTile(
leading: new Icon(Icons.help),
title: new Text("對話框列表2"),
),
new ListTile(
leading: new Icon(Icons.settings),
title: new Text("對話框列表3"),
),
new ListTile(
leading: new Icon(Icons.more),
title: new Text("對話框列表4"),
),
],
),
),
);
});
},
child: new Text("ModalBottomSheet"),
),
],
),
);
}
}