效果
大致思路
1、彈框整體實現 和寫界面是一樣的 畢竟flutter中 一切皆組件 界面 彈框 按鈕。。。。都是組件
2、樣式和跳轉要進行處理 背景色透明效果有兩種實現方式
a、界面跳轉中opaque: false可以設置下個界面背景透明
b、使用showDialog進行新界面跳轉
3、佈局中使用Material type: MaterialType.transparency設置爲背景透明
dialog相關代碼
///* 作者:guoyzh
///* 時間:2020/1/6
///* 功能:自定義dialog的抽取
class BaseDialog extends StatefulWidget {
final String title;
final String content;
final bool cancelAble;
final Function confirmCallback; // 點擊確定按鈕回調
final Function cancelCallback; // 點擊取消按鈕
final Function dismissCallback; // 彈窗關閉回調
BaseDialog(
{this.title = "",
this.content = "",
this.cancelAble = true,
this.confirmCallback,
this.cancelCallback,
this.dismissCallback});
@override
_BaseDialogState createState() => _BaseDialogState();
}
class _BaseDialogState extends State<BaseDialog> {
@override
Widget build(BuildContext context) {
// 設置彈框的寬度爲屏幕寬度的86%
var _dialogWidth = MediaQuery.of(context).size.width * 0.86;
// 構建彈框內容
Container _dialogContent = Container(
decoration: ShapeDecoration(
color: Color(0xffffffff),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(4.0),
),
),
),
child: Column(
// 主軸對齊方向
mainAxisAlignment: MainAxisAlignment.center,
// 另一個軸對齊方向
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// 標題
Padding(
padding: const EdgeInsets.fromLTRB(30, 0, 0, 0),
child: Text(
widget.title == "" ? "標題" : widget.title,
style: TextStyle(
color: Colors.black,
fontSize: 24,
fontWeight: FontWeight.w300),
),
),
// 內容
Padding(
padding: const EdgeInsets.fromLTRB(30, 12, 0, 0),
child: Text(
widget.content == "" ? "內容" : widget.content,
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
),
),
// 按鈕
Row(
children: <Widget>[
GestureDetector(
onTap: _clickCancel,
child: Padding(
padding: const EdgeInsets.fromLTRB(146, 26, 0, 0),
child: Text(
"取消",
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
),
),
),
GestureDetector(
onTap: _clickConfirm,
child: Padding(
padding: EdgeInsets.fromLTRB(52, 26, 0, 0),
child: Text(
"確定",
style: TextStyle(
color: Color.fromRGBO(233, 87, 14, 1),
fontSize: 18,
),
),
),
),
],
)
],
),
);
// 構建彈框佈局
return WillPopScope(
child: GestureDetector(
onTap: () => {widget.cancelAble ? _dismissDialog() : null},
child: Material(
type: MaterialType.transparency,
child: Center(
//保證控件居中效果
child: SizedBox(
// 設置彈框寬度
width: _dialogWidth,
height: 186.0,
child: _dialogContent,
),
),
),
),
onWillPop: () async {
return widget.cancelAble;
});
}
/// 點擊隱藏dialog
_dismissDialog() {
if (widget.dismissCallback != null) {
widget.dismissCallback();
}
Navigator.of(context).pop();
}
/// 點擊取消
void _clickCancel() {
if (widget.confirmCallback != null) {
widget.confirmCallback();
}
_dismissDialog();
}
/// 點擊確定
void _clickConfirm() {
if (widget.confirmCallback != null) {
widget.confirmCallback();
}
_dismissDialog();
}
}
展示彈框工具類方法
/// 展示dialog
static void showDialogs(BuildContext context, Widget dialog) {
// 導航到新路由 背景顏色爲透明色
/*Navigator.of(context).push(PageRouteBuilder(
opaque: false,
pageBuilder: (context, animation, secondaryAnimation) {
return dialog;
}));*/
showDialog(context: context, builder: (_) => dialog);
}
代碼中調用
AppUtils.showDialogs(context, BaseDialog(title: '提示', content: '確認退出?'));