flutter中使用弹窗应该用flutter提供的showDialog方法
void _showAlertDialog() async {
var res = await showDialog(
context: context,
child: AlertDialog(
title: Text('测试'),
content: Text('这是一个测试窗口'),
actions: [
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('确定')),
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('取消'))
],
));
print(res);
}
这里我们调用了showDialog()方法,传入参数:
在AlertDialog中,我们添加了一个title,content,以及两个按钮。按钮的点击事件,我们添加了
Navigator.of(context).pop();
点击两个按钮后,都会退出弹框。
运行结果:
而res的结果为null,原因是因为我们退出时并没有指定参数,我们也可以给它指定一个参数,类似于这样:
Navigator.of(context).pop("test");
这时候res的结果就会使test了
上面说了,showDialog()的child参数是一个组件,所以我们的自定义弹窗要继承自statelesswidget或者statefullwidget
/*
* @Author: wangyuyong
* @Date: 2020-07-21 09:24:59
* @LastEditTime: 2020-07-21 13:59:36
* @FilePath: /flutterdemo/lib/components/LoadingDialog.dart
* @Description:
*/
import 'package:flutter/material.dart';
class LoadingDialog extends StatefulWidget {
final Color _valueColor;
final String _content;
_LoadingDialogState state;
LoadingDialog(
{Key key, Color valueColor = Colors.red, String content = "加载中..."})
: this._valueColor = valueColor,
this._content = content,
super(key: key);
@override
_LoadingDialogState createState() => state = _LoadingDialogState(
valueColor: this._valueColor,
content: this._content,
);
bool isLoading() {
return state._isActive;
}
}
class _LoadingDialogState extends State {
final Color _valueColor;
final String _content;
bool _isActive = false;
_LoadingDialogState(
{Color valueColor = Colors.red, String content = "加载中..."})
: this._valueColor = valueColor,
this._content = content;
void initState() {
// loading弹窗当前为活跃界面
super.initState();
this._isActive = true;
}
@override
Widget build(BuildContext context) {
return Material(
// 设置透明
type: MaterialType.transparency,
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.white,
child: Stack(
children: [
Align(
child: CircularProgressIndicator(
strokeWidth: 4.0,
valueColor: new AlwaysStoppedAnimation(this._valueColor),
),
alignment: Alignment.center,
),
Align(
child: Padding(
padding: EdgeInsets.fromLTRB(10, 10, 10, 20),
child: Text(this._content),
),
alignment: Alignment.bottomCenter,
)
],
),
),
),
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
this._isActive = false;
}
}
在build中,我们使用Material这个组件,同时设置它的type为MaterialType.transparency,这样子就可以实现弹窗的背景是那种黑色半透明的效果了,接着就是一些常规布局了。
圆形进度条我们使用CircularProgressIndicator组件
CircularProgressIndicator(
strokeWidth: 4.0,
valueColor: new AlwaysStoppedAnimation(this._valueColor),
),
这里我们还需要提供一个isLoading的方法给外面调用,如果dialog没有处于界面,则不调用Navigator.of(context).pop(),如果dialog处于界面,在数据加载完成后,才能调用Navigator.of(context).pop()。
我们来使用一下这个弹窗:
void _showLoadingDialog() async {
var dialog = LoadingDialog();
showDialog(context: context, child: dialog);
Timer.periodic(Duration(milliseconds: 3000), (t) {
t.cancel();
if (dialog.isLoading()) {
Navigator.of(context).pop();
}
});
这里我使用了一个计时器Timer来模仿网络请求,演示结果:
略(嘿嘿嘿~没法上传视频,就不演示了)
到此,水文结束