背景
项目开发中碰到一个需求:监听接收流消息,每次使用 dialog 的方式弹窗显示,要求,每次弹窗将之前的弹窗关闭。
实现
为了达到这个效果,我们需要监听 dialog 的显隐状态,并提供方法关闭指定的dialog。
代码如下:
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
typedef DialogLifeCallback = Function(
bool show,
GlobalKey<BaseLifeDialogState>,
);
class BaseLifeDialog extends StatefulWidget {
final DialogLifeCallback callback;
final Widget child;
const BaseLifeDialog({
Key key,
@required this.callback,
@required this.child,
}) : super(key: key);
@override
BaseLifeDialogState createState() => BaseLifeDialogState();
}
class BaseLifeDialogState extends State<BaseLifeDialog> {
//flutter调度阶段是否为 build/layout/paint
bool get isPersistentCallbacks =>
SchedulerBinding.instance?.schedulerPhase ==
SchedulerPhase.persistentCallbacks;
@override
void initState() {
super.initState();
if (!mounted) return;
if (isPersistentCallbacks) {
SchedulerBinding.instance?.addPostFrameCallback((_) {
//回调告知 dialog 已显示
_noticeLife(true);
});
} else {
//回调告知 dialog 已显示
_noticeLife(true);
}
}
@override
void dispose() {
//回调告知 dialog 已消失
_noticeLife(false);
super.dispose();
}
void _noticeLife(bool isShow) {
widget.callback(isShow, widget.key);
}
///提供关闭自己的方法
void closeSelf() {
if (isPersistentCallbacks) {
SchedulerBinding.instance?.addPostFrameCallback((_) {
_closeSelf();
});
} else {
_closeSelf();
}
}
void _closeSelf() {
Navigator.of(context).removeRoute(ModalRoute.of(context));
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
- initState 将 dialog 显示状态传递出去
- dispose 将 dialog 消失状态传递出去
- 提供 closeSelf 关闭窗口方法,外部可通过 gloabalKey 进行调用
封装 dialog 管理工具类
(每次 showDialog 关闭之前未关闭的 dialog )
import 'package:flutter/material.dart';
import 'package:test_dialog_life/base_life_widget.dart';
class DialogController {
List<GlobalKey<BaseLifeDialogState>> _widgetKeys = [];
/// dialog 显隐 回调
void onListenDialogToggle(bool isShow, GlobalKey<BaseLifeDialogState> key) {
if (isShow) {
//dialog显示
//关闭之前的其他弹窗
_widgetKeys.forEach((element) {
element.currentState?.closeSelf();
});
_widgetKeys.add(key);
} else {
//dialog消失
if (_widgetKeys.contains(key)) {
_widgetKeys.remove(key);
}
}
}
//提供外部调用,showDialog
show(
BuildContext context,
Widget child,
) {
showDialog<bool>(
context: context,
barrierDismissible: false,
child: Builder(
builder: (context) {
return Dialog(
child: BaseLifeDialog(
key: GlobalKey<BaseLifeDialogState>(),
callback: onListenDialogToggle,
child: child,
),
);
},
),
);
}
///单例实现
DialogController._interval();
static DialogController _instance = DialogController._interval();
static DialogController get instance => _instance;
factory DialogController() => _instance;
}
Demo 调用示例:
//点击触发
onPressed: () {
DialogController.instance.show(context, DialogChild(msg: "1"));
DialogController.instance.show(context, DialogChild(msg: "2"));
}
class DialogChild extends StatelessWidget {
final String msg;
const DialogChild({Key key, this.msg}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 200,
width: 200,
child: Center(
child: Text(msg),
),
);
}
}
网友评论