show static method

void show(
  1. BuildContext context, {
  2. String? message,
  3. Widget? child,
  4. Widget? icon,
  5. Duration? fadeDuration,
  6. Duration? duration,
  7. double? fontSize,
  8. Color? textColor,
  9. Color? backgroundColor,
  10. EdgeInsets? padding,
  11. BorderRadius? borderRadius,
  12. BetterToastPosition position = BetterToastPosition.bottom,
  13. double? topOffset,
  14. double? bottomOffset,
  15. TextAlign? textAlign = TextAlign.center,
  16. bool? forbidClick = false,
  17. double? width,
  18. double? height,
  19. VoidCallback? onHide,
})

Implementation

static void show(
  BuildContext context, {

  /// Toast 的消息
  String? message,

  /// Toast 的子组件
  Widget? child,

  /// Toast 的图标
  Widget? icon,

  /// 动画持续时间
  Duration? fadeDuration,

  /// Toast 的持续时间
  Duration? duration,

  /// Toast 的字体大小
  double? fontSize,
  Color? textColor,

  /// Toast 的背景颜色
  Color? backgroundColor,

  /// Toast 的内边距
  EdgeInsets? padding,

  /// Toast 的圆角半径
  BorderRadius? borderRadius,

  /// Toast 的位置
  BetterToastPosition position = BetterToastPosition.bottom,

  /// 顶部偏移量
  double? topOffset,

  /// 底部偏移量
  double? bottomOffset,

  /// 文本对齐方式
  TextAlign? textAlign = TextAlign.center,

  /// 是否禁止点击
  bool? forbidClick = false,

  /// Toast 的宽度
  double? width,

  /// Toast 的高度
  double? height,
  VoidCallback? onHide,
}) {
  final overlay = Overlay.of(context);
  final screenHeight = BetterScreenUtil.screenHeight;
  topOffset ??= screenHeight * 0.2;
  bottomOffset ??= screenHeight * 0.2;

  // 动画控制器
  final animationController = AnimationController(
    vsync: overlay,
    duration: fadeDuration ?? const Duration(milliseconds: 250),
  );

  // 遮罩层控制器(仅当 forbidClick=true 时使用)
  final fadeController = AnimationController(
    vsync: overlay,
    duration: const Duration(milliseconds: 150),
  );
  final fadeAnimation = CurvedAnimation(
    parent: fadeController,
    curve: Curves.easeInOut,
  );

  // 位移动画
  final offsetAnimation =
      Tween<Offset>(
        begin: position == BetterToastPosition.center
            ? Offset.zero
            : Offset(0, position == BetterToastPosition.bottom ? 0.1 : -0.1),
        end: Offset.zero,
      ).animate(
        CurvedAnimation(
          parent: animationController,
          curve: Curves.easeOutQuad,
        ),
      );

  // 透明度动画
  final toastOpacityAnimation = Tween<double>(begin: 0, end: 1).animate(
    CurvedAnimation(parent: animationController, curve: Curves.easeIn),
  );

  // 创建OverlayEntry
  final overlayEntry = OverlayEntry(
    builder: (context) {
      return Stack(
        children: [
          // 禁止点击的遮罩层(条件渲染)
          if (forbidClick == true)
            Positioned.fill(
              child: FadeTransition(
                opacity: fadeAnimation,
                child: Container(color: Colors.transparent),
              ),
            ),

          // Toast内容
          Align(
            alignment: _getAlignment(position),
            child: SlideTransition(
              position: offsetAnimation,
              child: FadeTransition(
                opacity: toastOpacityAnimation,
                child: Material(
                  color: Colors.transparent,
                  child:
                      child ??
                      Container(
                        width: width,
                        height: height,
                        margin: EdgeInsets.only(
                          top: position == BetterToastPosition.top
                              ? (topOffset ?? 0)
                              : 0,
                          bottom: position == BetterToastPosition.bottom
                              ? (bottomOffset ?? 0)
                              : 0,
                        ),
                        constraints: BoxConstraints(
                          maxWidth:
                              width ?? BetterScreenUtil.screenWidth * 0.8,
                        ),
                        padding:
                            padding ??
                            EdgeInsets.symmetric(
                              horizontal: 12.bw,
                              vertical: 8.bw,
                            ),
                        decoration: BoxDecoration(
                          color:
                              backgroundColor ?? Colors.black.withAlpha(178),
                          borderRadius:
                              borderRadius ?? BorderRadius.circular(8.bw),
                        ),
                        child: Column(
                          mainAxisSize: MainAxisSize.min,
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            if (icon != null) icon,
                            if (icon != null && message != null)
                              SizedBox(height: 8.bw),
                            if (message != null)
                              Text(
                                message,
                                textAlign: textAlign,
                                style: TextStyle(
                                  color: textColor ?? Colors.white,
                                  fontSize: fontSize ?? 14.bsp,
                                ),
                              ),
                          ],
                        ),
                      ),
                ),
              ),
            ),
          ),
        ],
      );
    },
  );

  // 插入到Overlay
  overlay.insert(overlayEntry);

  // 启动动画(先显示遮罩层)
  void startAnimations() async {
    if (forbidClick == true) {
      await fadeController.forward();
    }
    await animationController.forward();
  }

  // 隐藏动画(先隐藏Toast再隐藏遮罩)
  Future<void> hideAnimations() async {
    await animationController.reverse();
    if (forbidClick == true) {
      await fadeController.reverse();
    }
    overlayEntry.remove();
    onHide?.call();
  }

  // 执行显示
  startAnimations();

  // 延迟隐藏
  Future.delayed(duration ?? const Duration(seconds: 2), hideAnimations);
}