| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547 |
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- import 'package:flutter_svg/flutter_svg.dart';
- import 'package:get/get.dart';
- import 'package:nomo/app/widgets/click_opacity.dart';
- import 'package:nomo/config/theme/theme_extensions/theme_extension.dart';
- /// 通用弹窗组件
- class CustomDialog {
- /// 显示成功弹窗(如Premium激活成功)
- static void showSuccess({
- required String title,
- required String message,
- String buttonText = 'Got it',
- VoidCallback? onPressed,
- IconData? icon,
- String? svgPath,
- Color? iconColor,
- Color? titleColor,
- Color? messageColor,
- }) {
- Get.generalDialog(
- pageBuilder: (context, animation, secondaryAnimation) {
- return _CustomDialogWidget(
- type: DialogType.success,
- title: title,
- message: message,
- buttonText: buttonText,
- onPressed: onPressed,
- icon: icon ?? Icons.workspace_premium,
- svgPath: svgPath,
- iconColor: iconColor ?? const Color(0xFFFF9500),
- titleColor: titleColor,
- messageColor: messageColor,
- animation: animation,
- );
- },
- barrierDismissible: false,
- transitionDuration: const Duration(milliseconds: 300),
- );
- }
- static void showUpdateDialog({
- required String title,
- required String message,
- String buttonText = 'Retry',
- String? cancelText,
- VoidCallback? onPressed,
- VoidCallback? onCancel,
- String? svgPath,
- Color? iconColor,
- Color? titleColor,
- Color? messageColor,
- Color? confirmButtonColor,
- Color? cancelButtonColor,
- }) {
- Get.generalDialog(
- pageBuilder: (context, animation, secondaryAnimation) {
- return WillPopScope(
- onWillPop: () async => false,
- child: _CustomDialogWidget(
- type: DialogType.error,
- title: title,
- message: message,
- buttonText: buttonText,
- cancelText: cancelText,
- onPressed: onPressed,
- onCancel: onCancel,
- svgPath: svgPath,
- iconColor:
- iconColor ?? Get.reactiveTheme.textTheme.bodyLarge!.color!,
- titleColor: titleColor,
- messageColor: messageColor,
- confirmButtonColor: confirmButtonColor,
- cancelButtonColor: cancelButtonColor,
- animation: animation,
- ),
- );
- },
- barrierDismissible: false,
- transitionDuration: const Duration(milliseconds: 300),
- );
- }
- /// 显示信息弹窗(如邮件发送成功)
- static void showInfo({
- required String title,
- required String message,
- String buttonText = 'OK',
- VoidCallback? onPressed,
- IconData? icon,
- String? svgPath,
- Color? iconColor,
- Color? titleColor,
- Color? messageColor,
- }) {
- Get.generalDialog(
- pageBuilder: (context, animation, secondaryAnimation) {
- return _CustomDialogWidget(
- type: DialogType.info,
- title: title,
- message: message,
- buttonText: buttonText,
- onPressed: onPressed,
- icon: icon ?? Icons.mark_email_read,
- svgPath: svgPath,
- iconColor: iconColor ?? const Color(0xFF00A8E8),
- titleColor: titleColor,
- messageColor: messageColor,
- animation: animation,
- );
- },
- barrierDismissible: false,
- transitionDuration: const Duration(milliseconds: 300),
- );
- }
- /// 显示错误弹窗(如网络连接错误)
- static void showError({
- required String title,
- required String message,
- String buttonText = 'Retry',
- String? cancelText,
- VoidCallback? onPressed,
- VoidCallback? onCancel,
- IconData? icon,
- String? svgPath,
- Color? iconColor,
- Color? titleColor,
- Color? messageColor,
- Color? confirmButtonColor,
- Color? cancelButtonColor,
- String? errorCode,
- }) {
- Get.generalDialog(
- pageBuilder: (context, animation, secondaryAnimation) {
- return _CustomDialogWidget(
- type: DialogType.error,
- title: title,
- message: message,
- buttonText: buttonText,
- cancelText: cancelText,
- onPressed: onPressed,
- onCancel: onCancel,
- icon: icon ?? Icons.wifi_off,
- svgPath: svgPath,
- iconColor: iconColor ?? const Color(0xFFFF9500),
- titleColor: titleColor,
- messageColor: messageColor,
- confirmButtonColor:
- confirmButtonColor ?? Get.reactiveTheme.primaryColor,
- cancelButtonColor: cancelButtonColor,
- errorCode: errorCode,
- animation: animation,
- );
- },
- barrierDismissible: false,
- transitionDuration: const Duration(milliseconds: 300),
- );
- }
- /// 显示确认弹窗(如退出登录确认)
- static void showConfirm({
- required String title,
- required String message,
- String confirmText = 'Confirm',
- String cancelText = 'Cancel',
- required VoidCallback onConfirm,
- VoidCallback? onCancel,
- IconData? icon,
- String? svgPath,
- Color? iconColor,
- Color? titleColor,
- Color? messageColor,
- Color? confirmButtonColor,
- Color? cancelButtonColor,
- }) {
- Get.generalDialog(
- pageBuilder: (context, animation, secondaryAnimation) {
- return _CustomDialogWidget(
- type: DialogType.confirm,
- title: title,
- message: message,
- buttonText: confirmText, // 添加必需的参数
- confirmText: confirmText,
- cancelText: cancelText,
- onConfirm: onConfirm,
- onCancel: onCancel,
- icon: icon ?? Icons.info_outline,
- svgPath: svgPath,
- iconColor: iconColor ?? const Color(0xFFFF3B30),
- titleColor: titleColor,
- messageColor: messageColor,
- confirmButtonColor: confirmButtonColor ?? const Color(0xFFFF3B30),
- cancelButtonColor: cancelButtonColor,
- animation: animation,
- );
- },
- barrierDismissible: true,
- barrierLabel: 'Dismiss',
- transitionDuration: const Duration(milliseconds: 300),
- );
- }
- }
- /// 弹窗类型枚举
- enum DialogType { success, info, error, confirm }
- /// 自定义弹窗组件
- class _CustomDialogWidget extends StatelessWidget {
- final DialogType type;
- final String title;
- final String message;
- final String buttonText;
- final String? confirmText;
- final String? cancelText;
- final VoidCallback? onPressed;
- final VoidCallback? onConfirm;
- final VoidCallback? onCancel;
- final IconData? icon;
- final String? svgPath;
- final Color iconColor;
- final Color? titleColor;
- final Color? messageColor;
- final Color? confirmButtonColor;
- final Color? cancelButtonColor;
- final String? errorCode;
- final Animation<double>? animation;
- const _CustomDialogWidget({
- required this.type,
- required this.title,
- required this.message,
- required this.buttonText,
- this.confirmText,
- this.cancelText,
- this.onPressed,
- this.onConfirm,
- this.onCancel,
- this.icon,
- this.svgPath,
- required this.iconColor,
- this.titleColor,
- this.messageColor,
- this.confirmButtonColor,
- this.cancelButtonColor,
- this.errorCode,
- this.animation,
- });
- @override
- Widget build(BuildContext context) {
- if (animation == null) {
- // 如果没有动画,返回普通弹窗
- return _buildDialog();
- }
- // 使用动画构建弹窗
- return _buildAnimatedDialog();
- }
- /// 构建普通弹窗
- Widget _buildDialog() {
- return Dialog(
- backgroundColor: Colors.transparent,
- insetPadding: EdgeInsets.symmetric(horizontal: 24.w),
- child: _buildDialogContent(),
- );
- }
- /// 构建带动画的弹窗
- Widget _buildAnimatedDialog() {
- return Dialog(
- backgroundColor: Colors.transparent,
- insetPadding: EdgeInsets.symmetric(horizontal: 24.w),
- child: AnimatedBuilder(
- animation: animation!,
- builder: (context, child) {
- // 使用不同的曲线来避免关闭时的抖动
- final scaleValue = Tween<double>(begin: 0.8, end: 1.0)
- .animate(
- CurvedAnimation(
- parent: animation!,
- curve: Curves.easeOutCubic,
- reverseCurve: Curves.easeInCubic,
- ),
- )
- .value;
- final offsetValue = Tween<double>(begin: 30, end: 0)
- .animate(
- CurvedAnimation(
- parent: animation!,
- curve: Curves.easeOutCubic,
- reverseCurve: Curves.easeInCubic,
- ),
- )
- .value;
- return Transform.scale(
- scale: scaleValue,
- child: Transform.translate(
- offset: Offset(0, offsetValue),
- child: Opacity(opacity: animation!.value, child: child),
- ),
- );
- },
- child: _buildDialogContent(),
- ),
- );
- }
- /// 构建弹窗内容
- Widget _buildDialogContent() {
- return Container(
- padding: EdgeInsets.all(24.w),
- decoration: BoxDecoration(
- color: Get.reactiveTheme.highlightColor,
- borderRadius: BorderRadius.circular(16.r),
- ),
- child: Column(
- mainAxisSize: MainAxisSize.min,
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // 图标
- _buildIcon(),
- // 标题和消息
- _buildContent(),
- 24.verticalSpaceFromWidth,
- // 按钮
- _buildButtons(),
- ],
- ),
- );
- }
- /// 构建图标
- Widget _buildIcon() {
- return Container(
- margin: EdgeInsets.only(bottom: 10.w),
- child: svgPath != null
- ? SvgPicture.asset(
- svgPath!,
- width: 40.w,
- height: 40.w,
- colorFilter: ColorFilter.mode(iconColor, BlendMode.srcIn),
- )
- : Icon(icon ?? Icons.info_outline, size: 40.w, color: iconColor),
- );
- }
- /// 构建内容区域
- Widget _buildContent() {
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- // 标题
- Text(
- title,
- style: TextStyle(
- fontSize: 22.sp,
- fontWeight: FontWeight.w500,
- color: titleColor ?? Get.reactiveTheme.textTheme.bodyLarge!.color,
- ),
- ),
- 18.verticalSpaceFromWidth,
- // 消息
- Text(
- message,
- style: TextStyle(
- fontSize: 14.sp,
- color: messageColor ?? Get.reactiveTheme.hintColor,
- height: 1.4,
- ),
- ),
- ],
- );
- }
- /// 构建按钮区域
- Widget _buildButtons() {
- switch (type) {
- case DialogType.success:
- case DialogType.info:
- return _buildSingleButton();
- case DialogType.error:
- return _buildErrorButtons();
- case DialogType.confirm:
- return _buildConfirmButtons();
- }
- }
- /// 构建单个按钮
- Widget _buildSingleButton() {
- return SizedBox(
- width: double.infinity,
- height: 42.w,
- child: ClickOpacity(
- onTap: () {
- onPressed?.call();
- },
- child: Container(
- decoration: BoxDecoration(
- color: confirmButtonColor ?? Get.reactiveTheme.primaryColor,
- borderRadius: BorderRadius.circular(8.r),
- ),
- alignment: Alignment.center,
- child: Text(
- buttonText,
- style: TextStyle(
- fontSize: 14.sp,
- fontWeight: FontWeight.w600,
- color: Colors.white,
- ),
- ),
- ),
- ),
- );
- }
- /// 构建错误弹窗按钮
- Widget _buildErrorButtons() {
- return Column(
- children: [
- SizedBox(
- width: double.infinity,
- height: 42.h,
- child: ClickOpacity(
- onTap: () {
- onPressed?.call();
- },
- child: Container(
- decoration: BoxDecoration(
- color: confirmButtonColor ?? Get.reactiveTheme.primaryColor,
- borderRadius: BorderRadius.circular(8.r),
- ),
- alignment: Alignment.center,
- child: Text(
- buttonText,
- style: TextStyle(
- fontSize: 14.sp,
- fontWeight: FontWeight.w600,
- color: Colors.white,
- ),
- ),
- ),
- ),
- ),
- if (cancelText != null) ...[
- SizedBox(height: 12.w),
- SizedBox(
- width: double.infinity,
- height: 42.h,
- child: ClickOpacity(
- onTap: () {
- onCancel?.call();
- },
- child: Container(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8.r),
- border: Border.all(
- color: cancelButtonColor ?? Get.reactiveTheme.dividerColor,
- width: 1.w,
- ),
- ),
- alignment: Alignment.center,
- child: Text(
- cancelText!,
- style: TextStyle(
- fontSize: 14.sp,
- fontWeight: FontWeight.w600,
- color: cancelButtonColor ?? Get.reactiveTheme.hintColor,
- ),
- ),
- ),
- ),
- ),
- ],
- ],
- );
- }
- /// 构建确认弹窗按钮
- Widget _buildConfirmButtons() {
- return Column(
- children: [
- SizedBox(
- width: double.infinity,
- height: 42.w,
- child: ClickOpacity(
- onTap: () {
- onConfirm?.call();
- },
- child: Container(
- decoration: BoxDecoration(
- color: confirmButtonColor ?? iconColor,
- borderRadius: BorderRadius.circular(8.r),
- ),
- alignment: Alignment.center,
- child: Text(
- confirmText ?? 'Confirm',
- style: TextStyle(
- fontSize: 14.sp,
- fontWeight: FontWeight.w600,
- color: Colors.white,
- ),
- ),
- ),
- ),
- ),
- 8.verticalSpace,
- SizedBox(
- width: double.infinity,
- height: 42.w,
- child: ClickOpacity(
- onTap: () {
- onCancel?.call();
- },
- child: Container(
- decoration: BoxDecoration(
- borderRadius: BorderRadius.circular(8.r),
- border: Border.all(
- color: cancelButtonColor ?? Get.reactiveTheme.dividerColor,
- width: 1.w,
- ),
- ),
- alignment: Alignment.center,
- child: Text(
- cancelText ?? 'Cancel',
- style: TextStyle(
- fontSize: 14.sp,
- fontWeight: FontWeight.w600,
- color: cancelButtonColor ?? Get.reactiveTheme.hintColor,
- ),
- ),
- ),
- ),
- ),
- ],
- );
- }
- }
|