Skip to content

Commit

Permalink
refactor: Use Stack instead of Overlay
Browse files Browse the repository at this point in the history
  • Loading branch information
MMMzq committed Apr 23, 2020
1 parent fae2ba1 commit 58eb6cb
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 73 deletions.
44 changes: 6 additions & 38 deletions lib/src/bot_toast_init.dart
Expand Up @@ -3,15 +3,14 @@ import 'package:flutter/material.dart';
import 'basis.dart';
import 'bot_toast_manager.dart';

final GlobalKey<BotToastInitState> _botToastInitKey =
GlobalKey<BotToastInitState>();
final GlobalKey<BotToastManagerState> _key =
GlobalKey<BotToastManagerState>();

BotToastManager get botToastManager {
assert(_botToastInitKey?.currentState?._botToastManager != null);
return _botToastInitKey.currentState._botToastManager;
BotToastManagerState get botToastManager {
assert(_key?.currentState != null);
return _key.currentState;
}


class BotToastWidgetsBindingObserver with WidgetsBindingObserver {

BotToastWidgetsBindingObserver._(){
Expand Down Expand Up @@ -53,38 +52,7 @@ TransitionBuilder BotToastInit() {
//确保提前初始化,保证WidgetsBinding.instance.addObserver(this);的顺序
BotToastWidgetsBindingObserver._singleton;
return (_, Widget child) {
return _BotToastInit(child: child);
return BotToastManager(key: _key, child: child);
};
}

class _BotToastInit extends Overlay {
final Widget child;

_BotToastInit({@required this.child})
: assert(child != null),
super(key: _botToastInitKey,
initialEntries: [
OverlayEntry(maintainState: true, builder: (_) => child)
]);

@override
BotToastInitState createState() => BotToastInitState();
}

class BotToastInitState extends OverlayState {

BotToastManager _botToastManager;

@override
void initState() {
super.initState();
_botToastManager = BotToastManager(this);
}

@override
void dispose() {
super.dispose();
_botToastManager.dispose();
}

}
72 changes: 37 additions & 35 deletions lib/src/bot_toast_manager.dart
@@ -1,79 +1,81 @@

import 'package:bot_toast/src/toast_widget/toast_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

import 'bot_toast_init.dart';

void safeRun(void Function() callback) {
SchedulerBinding.instance.addPostFrameCallback((_) {
callback();
});
SchedulerBinding.instance.ensureVisualUpdate();
}

class BotToastManager {
final Map<String, Map<UniqueKey, OverlayEntry>> _map = {};
final BotToastInitState _botToastInitState;
class BotToastManager extends StatefulWidget {
final Widget child;

BotToastManager(this._botToastInitState);
const BotToastManager({Key key, this.child}) : super(key: key);

@override
BotToastManagerState createState() => BotToastManagerState();
}

void dispose() {
_children.forEach((item) {
item.remove();
});
_map.clear();
}
class BotToastManagerState extends State<BotToastManager> {
final Map<String, Map<UniqueKey, Widget>> _map = {};

List<OverlayEntry> get _children =>
List<Widget> get _children =>
_map.values.fold([], (value, items) {
return value..addAll(items.values);
});

void insert(String groupKey, UniqueKey key, Widget widget) {
safeRun(() {
assert(_botToastInitState != null);
_map[groupKey] ??= {};
final uniqueKey = UniqueKey();
final overlayEntry = OverlayEntry(builder: (_) =>
ProxyDispose(key: uniqueKey, child: widget, disposeCallback: () {
_map[groupKey]?.remove(key);
},));
_map[groupKey][key] = overlayEntry;
_botToastInitState.insert(overlayEntry);
widget = ProxyDispose(
key: uniqueKey,
child: widget,
disposeCallback: () {
_map[groupKey]?.remove(key);
},
);
_map[groupKey][key] = widget;
_update();
});
}

void remove(String groupKey, UniqueKey key) {
safeRun(() {
final result = _map[groupKey]?.remove(key);
if (result != null) {
result.remove();
}
_map[groupKey]?.remove(key);
_update();
});
}

void removeAll(String groupKey) {
safeRun(() {
_map[groupKey]?.forEach((key, value) {
assert(value != null);
value.remove();
});
_map[groupKey]?.clear();
_update();
});
}

void cleanAll() {
safeRun(() {
List<OverlayEntry> children = _children;
assert(children.every((test) => test != null));
children.forEach((item) {
item.remove();
});
_map.clear();
_update();
});
}
}

void _update() {
if (mounted) {
setState(() {});
}
}

@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
widget.child,
]
..addAll(_children),
);
}
}

0 comments on commit 58eb6cb

Please sign in to comment.