Skip to content

Commit b79da05

Browse files
committed
add bindWidget feature
1 parent 9a87bef commit b79da05

File tree

11 files changed

+172
-25
lines changed

11 files changed

+172
-25
lines changed

example/lib/main.dart

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,42 @@ class SmartDialogPage extends StatelessWidget {
6262
print('--------------------------');
6363
}
6464

65-
void _show() {
66-
SmartDialog.show(builder: (_) {
67-
return Container(
68-
height: 80,
69-
width: 180,
70-
decoration: BoxDecoration(
71-
color: Colors.black,
72-
borderRadius: BorderRadius.circular(10),
73-
),
74-
alignment: Alignment.center,
75-
child: Text(
76-
'easy custom dialog',
77-
style: TextStyle(color: Colors.white),
78-
),
65+
void _show() async {
66+
//关闭多个相同tag dialog
67+
tagDialog(String tag) {
68+
SmartDialog.show(
69+
tag: tag,
70+
builder: (_) {
71+
return Container(
72+
height: 80,
73+
width: 180,
74+
decoration: BoxDecoration(
75+
color: Colors.black,
76+
borderRadius: BorderRadius.circular(10),
77+
),
78+
alignment: Alignment.center,
79+
child: Text(
80+
'easy custom dialog',
81+
style: TextStyle(color: Colors.white),
82+
),
83+
);
84+
},
7985
);
80-
});
86+
}
87+
var tag = "1";
88+
for (var i = 0; i < 3; i++) {
89+
tagDialog(tag);
90+
await Future.delayed(Duration(milliseconds: 300));
91+
}
92+
SmartDialog.dismiss(tag: tag, status: SmartStatus.allDialog);
93+
94+
//穿透遮罩
95+
SmartDialog.show(
96+
usePenetrate: true,
97+
builder: (_) {
98+
return Container(height: 80, width: 180, color: Colors.black);
99+
},
100+
);
81101
}
82102

83103
void _showAttach(BuildContext ctx) {

lib/src/compatible/compatible_smart_dialog.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ class CompatibleSmartDialog {
142142
permanent: false,
143143
useSystem: useSystem ?? false,
144144
bindPage: false,
145+
bindWidget: null,
145146
);
146147
}
147148

@@ -304,6 +305,7 @@ class CompatibleSmartDialog {
304305
permanent: false,
305306
useSystem: useSystem ?? false,
306307
bindPage: false,
308+
bindWidget: null,
307309
);
308310
}
309311

lib/src/custom/custom_dialog.dart

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
55
import 'package:flutter_smart_dialog/src/data/dialog_info.dart';
66
import 'package:flutter_smart_dialog/src/data/smart_tag.dart';
77
import 'package:flutter_smart_dialog/src/helper/dialog_proxy.dart';
8+
import 'package:flutter_smart_dialog/src/helper/monitor_widget_helper.dart';
89
import 'package:flutter_smart_dialog/src/helper/route_record.dart';
910
import 'package:flutter_smart_dialog/src/util/view_utils.dart';
1011
import 'package:flutter_smart_dialog/src/widget/attach_dialog_widget.dart';
@@ -56,6 +57,7 @@ class CustomDialog extends BaseDialog {
5657
required bool permanent,
5758
required bool useSystem,
5859
required bool bindPage,
60+
required BuildContext? bindWidget,
5961
}) {
6062
if (!_handleMustOperate(
6163
tag: displayTime != null ? _getTimeKey(displayTime) : tag,
@@ -66,6 +68,7 @@ class CustomDialog extends BaseDialog {
6668
permanent: permanent,
6769
useSystem: useSystem,
6870
bindPage: bindPage,
71+
bindWidget: bindWidget,
6972
)) return Future.value(null);
7073
return mainDialog.show<T>(
7174
widget: widget,
@@ -116,6 +119,7 @@ class CustomDialog extends BaseDialog {
116119
required bool permanent,
117120
required bool useSystem,
118121
required bool bindPage,
122+
required BuildContext? bindWidget,
119123
}) {
120124
if (!_handleMustOperate(
121125
tag: displayTime != null ? _getTimeKey(displayTime) : tag,
@@ -126,6 +130,7 @@ class CustomDialog extends BaseDialog {
126130
permanent: permanent,
127131
useSystem: useSystem,
128132
bindPage: bindPage,
133+
bindWidget: bindWidget,
129134
)) return Future.value(null);
130135
return mainDialog.showAttach<T>(
131136
targetContext: targetContext,
@@ -177,6 +182,7 @@ class CustomDialog extends BaseDialog {
177182
required bool permanent,
178183
required bool useSystem,
179184
required bool bindPage,
185+
required BuildContext? bindWidget,
180186
}) {
181187
// debounce
182188
if (!_checkDebounce(debounce, type)) return false;
@@ -190,6 +196,7 @@ class CustomDialog extends BaseDialog {
190196
permanent: permanent,
191197
useSystem: useSystem,
192198
bindPage: bindPage,
199+
bindWidget: bindWidget,
193200
);
194201

195202
SmartDialog.config.custom.isExist = DialogType.custom == type;
@@ -205,7 +212,12 @@ class CustomDialog extends BaseDialog {
205212
required bool permanent,
206213
required bool useSystem,
207214
required bool bindPage,
215+
required BuildContext? bindWidget,
208216
}) {
217+
if (bindWidget != null) {
218+
tag = tag ?? "${bindPage.hashCode}";
219+
}
220+
209221
if (keepSingle) {
210222
DialogInfo? dialogInfo = _getDialog(tag: SmartTag.keepSingle);
211223
if (dialogInfo == null) {
@@ -218,6 +230,7 @@ class CustomDialog extends BaseDialog {
218230
useSystem: useSystem,
219231
bindPage: bindPage,
220232
route: RouteRecord.curRoute,
233+
bindWidget: bindWidget,
221234
);
222235
_pushDialog(dialogInfo);
223236
mainDialogSingle = mainDialog;
@@ -237,6 +250,7 @@ class CustomDialog extends BaseDialog {
237250
useSystem: useSystem,
238251
bindPage: bindPage,
239252
route: RouteRecord.curRoute,
253+
bindWidget: bindWidget,
240254
);
241255
_pushDialog(dialogInfo);
242256
}
@@ -248,6 +262,10 @@ class CustomDialog extends BaseDialog {
248262
} else {
249263
proxy.dialogQueue.addLast(dialogInfo);
250264
}
265+
if (dialogInfo.bindWidget != null) {
266+
MonitorWidgetHelper.instance.monitorDialogQueue.add(dialogInfo);
267+
}
268+
251269
// insert the dialog carrier into the page
252270
ViewUtils.addSafeUse(() {
253271
Overlay.of(DialogProxy.contextOverlay)!.insert(
@@ -356,6 +374,9 @@ class CustomDialog extends BaseDialog {
356374
//handle close dialog
357375
var proxy = DialogProxy.instance;
358376
proxy.dialogQueue.remove(info);
377+
if (info.bindWidget != null) {
378+
MonitorWidgetHelper.instance.monitorDialogQueue.remove(info);
379+
}
359380

360381
//check if the queue contains a custom dialog or attach dialog
361382
proxy.config.custom.isExist = false;
@@ -410,8 +431,12 @@ class CustomDialog extends BaseDialog {
410431
//handle normal dialog
411432
for (var i = dialogQueue.length - 1; i >= 0; i--) {
412433
if (dialogQueue.isEmpty) break;
413-
if (type == DialogType.dialog || list[i].type == type) {
414-
info = list[i];
434+
var item = list[i];
435+
if (!item.dialog.mainDialog.visible) {
436+
continue;
437+
}
438+
if (type == DialogType.dialog || item.type == type) {
439+
info = item;
415440
break;
416441
}
417442
}

lib/src/custom/main_dialog.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class MainDialog {
2020
final SmartOverlayEntry overlayEntry;
2121
final _uniqueKey = UniqueKey();
2222

23-
bool offstage = false;
23+
bool visible = true;
2424
BaseController? _controller;
2525
Completer? _completer;
2626
VoidCallback? _onDismiss;
@@ -201,5 +201,5 @@ class MainDialog {
201201
);
202202
}
203203

204-
Widget getWidget() => Offstage(offstage: offstage, child: _widget);
204+
Widget getWidget() => Offstage(offstage: !visible, child: _widget);
205205
}

lib/src/data/base_dialog.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,14 @@ class BaseDialog {
1515

1616
/// get Widget : must implement
1717
Widget getWidget() => mainDialog.getWidget();
18+
19+
void appear(){
20+
mainDialog.visible = true;
21+
overlayEntry.markNeedsBuild();
22+
}
23+
24+
void hide() {
25+
mainDialog.visible = false;
26+
overlayEntry.markNeedsBuild();
27+
}
1828
}

lib/src/data/dialog_info.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class DialogInfo {
1313
required this.useSystem,
1414
required this.bindPage,
1515
required this.route,
16+
required this.bindWidget,
1617
});
1718

1819
final BaseDialog dialog;
@@ -21,7 +22,7 @@ class DialogInfo {
2122

2223
final DialogType type;
2324

24-
final String? tag;
25+
String? tag;
2526

2627
final bool permanent;
2728

@@ -30,4 +31,6 @@ class DialogInfo {
3031
final bool bindPage;
3132

3233
final Route<dynamic>? route;
34+
35+
final BuildContext? bindWidget;
3336
}

lib/src/helper/dialog_proxy.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class DialogProxy {
7373
required bool permanent,
7474
required bool useSystem,
7575
required bool bindPage,
76+
required BuildContext? bindWidget,
7677
}) {
7778
CustomDialog? dialog;
7879
var entry = SmartOverlayEntry(
@@ -100,6 +101,7 @@ class DialogProxy {
100101
permanent: permanent,
101102
useSystem: useSystem,
102103
bindPage: bindPage,
104+
bindWidget: bindWidget,
103105
);
104106
}
105107

@@ -129,6 +131,7 @@ class DialogProxy {
129131
required bool permanent,
130132
required bool useSystem,
131133
required bool bindPage,
134+
required BuildContext? bindWidget,
132135
}) {
133136
CustomDialog? dialog;
134137
var entry = SmartOverlayEntry(
@@ -161,6 +164,7 @@ class DialogProxy {
161164
permanent: permanent,
162165
useSystem: useSystem,
163166
bindPage: bindPage,
167+
bindWidget: bindWidget,
164168
);
165169
}
166170

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import 'dart:collection';
2+
3+
import 'package:flutter/rendering.dart';
4+
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
5+
import 'package:flutter_smart_dialog/src/util/log.dart';
6+
import 'package:flutter_smart_dialog/src/util/view_utils.dart';
7+
8+
import '../data/dialog_info.dart';
9+
10+
class MonitorWidgetHelper {
11+
factory MonitorWidgetHelper() => instance;
12+
static MonitorWidgetHelper? _instance;
13+
14+
static MonitorWidgetHelper get instance =>
15+
_instance ??= MonitorWidgetHelper._internal();
16+
17+
late Queue<DialogInfo> monitorDialogQueue;
18+
19+
bool prohibitMonitor = false;
20+
21+
MonitorWidgetHelper._internal() {
22+
monitorDialogQueue = ListQueue();
23+
24+
schedulerBinding.addPersistentFrameCallback((timeStamp) {
25+
if (monitorDialogQueue.isEmpty || prohibitMonitor) {
26+
return;
27+
}
28+
29+
prohibitMonitor = true;
30+
var removeList = <DialogInfo>[];
31+
monitorDialogQueue.forEach((item) {
32+
try {
33+
var context = item.bindWidget;
34+
if (context == null) {
35+
throw Error();
36+
}
37+
38+
var renderObject = context.findRenderObject();
39+
var viewport = RenderAbstractViewport.of(renderObject);
40+
var revealedOffset = viewport?.getOffsetToReveal(renderObject!, 0.0);
41+
if (revealedOffset?.rect.hasNaN ?? false) {
42+
item.dialog.hide();
43+
} else {
44+
item.dialog.appear();
45+
}
46+
} catch (e) {
47+
removeList.add(item);
48+
SmartLog.d(
49+
"The element(hashcode: ${item.bindWidget.hashCode}) is recycled and"
50+
" the 'bindWidget' dialog dismiss automatically",
51+
);
52+
}
53+
});
54+
for (var i = removeList.length; i > 0; i--) {
55+
SmartDialog.dismiss(tag: removeList[i - 1].tag);
56+
}
57+
prohibitMonitor = false;
58+
});
59+
}
60+
}

lib/src/helper/route_record.dart

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class RouteRecord {
5454
}
5555
} else {
5656
// deal with bindPage and permanent dialog
57-
if (info.dialog.mainDialog.offstage || info.permanent) {
57+
if (!info.dialog.mainDialog.visible || info.permanent) {
5858
shouldHandle = false;
5959
}
6060
}
@@ -71,8 +71,7 @@ class RouteRecord {
7171
if (curRoute == null || DialogProxy.instance.dialogQueue.isEmpty) return;
7272
for (var item in DialogProxy.instance.dialogQueue) {
7373
if (item.route == curRoute && item.bindPage) {
74-
item.dialog.mainDialog.offstage = true;
75-
item.dialog.overlayEntry.markNeedsBuild();
74+
item.dialog.hide();
7675
}
7776
}
7877
}
@@ -81,8 +80,7 @@ class RouteRecord {
8180
if (curRoute == null || DialogProxy.instance.dialogQueue.isEmpty) return;
8281
for (var item in DialogProxy.instance.dialogQueue) {
8382
if (item.route == curRoute && item.bindPage) {
84-
item.dialog.mainDialog.offstage = false;
85-
item.dialog.overlayEntry.markNeedsBuild();
83+
item.dialog.appear();
8684
}
8785
}
8886
}

0 commit comments

Comments
 (0)