insert<T> method

Future<T?> insert<T>(
  1. BuildContext context, {
  2. required AnimatedTransitionBuilder builder,
  3. String? key,
  4. Widget? child,
  5. bool opaque = false,
  6. bool replace = true,
  7. Color? barrierColor,
  8. bool dismissible = false,
  9. bool interceptPop = true,
  10. VoidCallback? onOutsideTap,
  11. bool maintainState = false,
  12. bool canSizeOverlay = false,
  13. Duration? animationDuration,
  14. CustomOverlayToken<T>? token,
  15. AlignmentGeometry alignment = Alignment.center,
})

Implementation

Future<T?> insert<T>(
  BuildContext context, {
  required AnimatedTransitionBuilder builder,
  String? key,
  Widget? child,
  bool opaque = false,
  bool replace = true, // 如果数量超过限制,是否替换最早的弹层,false则不弹出
  Color? barrierColor,
  bool dismissible = false,
  bool interceptPop = true,
  VoidCallback? onOutsideTap,
  bool maintainState = false,
  bool canSizeOverlay = false,
  Duration? animationDuration,
  CustomOverlayToken<T>? token,
  AlignmentGeometry alignment = Alignment.center,
}) async {
  // 检查弹层数量是否超出限制以及是否需要移除
  if (!_checkOverlayCount(replace)) return null;
  // 创建初始化字段
  OverlayEntry? overlayEntry;
  token ??= CustomOverlayToken<T>();
  final overlayState = Overlay.of(context);
  key ??= DateTime.now().microsecondsSinceEpoch.toString();
  final themeData = CustomOverlayThemeData.of(context);
  final animation = _OverlayAnimation(
    vsync: overlayState,
    duration: animationDuration ?? themeData.animationDuration,
  );
  final overlayPop = _OverlayPop<T>(
    context,
    canPop: true,
    overlayKey: key,
    autoRegister: interceptPop,
    onPop: (v) => cancel(key!, v),
    onDidPop: () => animation.dispose(),
  );
  try {
    // 插入覆盖层
    overlayState.insert(
      overlayEntry = OverlayEntry(
        opaque: opaque,
        maintainState: maintainState,
        canSizeOverlay: canSizeOverlay,
        builder: (context) {
          WidgetsBinding.instance.addPostFrameCallback(
            (_) => animation.forward(),
          );
          return CustomOverlayView(
            alignment: alignment,
            barrierColor: barrierColor,
            barrierAnimation: animation.barrier,
            overlayAnimation: animation.overlay,
            onOutsideTap: () {
              if (onOutsideTap != null) return onOutsideTap();
              if (dismissible) cancel(key!);
            },
            builder: (_, child) {
              return builder(context, animation.overlay, child);
            },
            child: child,
          );
        },
      ),
    );
    token._setOverlayEntry(overlayEntry);
    // 处理弹层后续事件
    final result = await (_overlayTokens[key] = token).whenCancel;
    if (token.withAnime) await animation.reverse();
    return result;
  } catch (e) {
    if (kDebugMode) print('弹窗异常:${e.toString()}');
  } finally {
    animation.dispose();
    overlayPop.unregister();
    _overlayTokens.remove(key);
  }
  return null;
}