hi-client/lib/app/widgets/dialogs/hi_dialog.dart

252 lines
8.3 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
class HIDialog extends StatefulWidget {
final String? title;
final String? message;
final String? confirmText;
final String? cancelText;
final VoidCallback? onConfirm;
final VoidCallback? onCancel;
final Widget? customMessageWidget;
/// 是否允许点击外部关闭
final bool barrierDismissible;
/// 是否禁止物理返回键关闭
final bool preventBackDismiss;
/// 是否点击确认后自动关闭(默认 true
final bool autoClose;
/// 是否显示按钮 loadingautoClose=false 时自动启用)
final bool? showLoading;
const HIDialog({
Key? key,
this.title,
this.message,
this.confirmText,
this.cancelText,
this.onConfirm,
this.onCancel,
this.customMessageWidget,
this.barrierDismissible = true,
this.preventBackDismiss = false,
this.autoClose = true,
this.showLoading,
}) : super(key: key);
static Future<void> show({
String? title,
String? message,
String? confirmText,
String? cancelText,
VoidCallback? onConfirm,
VoidCallback? onCancel,
Widget? customMessageWidget,
bool barrierDismissible = true,
bool preventBackDismiss = false,
bool autoClose = true,
bool? showLoading,
}) {
return Get.dialog(
HIDialog(
title: title,
message: message,
confirmText: confirmText,
cancelText: cancelText,
onConfirm: onConfirm,
onCancel: onCancel,
customMessageWidget: customMessageWidget,
barrierDismissible: barrierDismissible,
preventBackDismiss: preventBackDismiss,
autoClose: autoClose,
showLoading: showLoading,
),
barrierDismissible: barrierDismissible,
barrierColor: Colors.transparent,
);
}
@override
State<HIDialog> createState() => _HIDialogState();
}
class _HIDialogState extends State<HIDialog> {
bool _isLoading = false;
Future<void> _handleConfirm() async {
if (_isLoading) return;
final useLoading = widget.showLoading ?? !widget.autoClose;
if (useLoading) {
setState(() => _isLoading = true);
}
if (widget.autoClose) {
Get.back();
}
await Future.microtask(() => widget.onConfirm?.call());
if (useLoading && mounted) {
setState(() => _isLoading = false);
}
}
Widget _buildConfirmButton() {
return TextButton(
onPressed: _isLoading ? null : _handleConfirm,
style: TextButton.styleFrom(
backgroundColor: const Color(0xFFADFF5B),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.r),
),
minimumSize: Size(85.w, 40.w),
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: _isLoading
? SizedBox(
height: 20.w,
width: 20.w,
child: const CircularProgressIndicator(
color: Colors.black,
strokeWidth: 2,
),
)
: Text(
widget.confirmText ?? (widget.cancelText == null ? '好的' : AppTranslations.kr_dialog.kr_confirm),
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: 'AlibabaPuHuiTi-Medium',
),
),
);
}
@override
Widget build(BuildContext context) {
final dialog = Dialog(
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(20.w),
child: Transform.translate(
offset: Offset(0, -30.w),
child: ClipRRect(
borderRadius: BorderRadius.circular(34.r),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 26, sigmaY: 26), // 毛玻璃模糊
child: Container(
width: 245.w,
padding: EdgeInsets.fromLTRB(30.w, 16.w, 30.w, 16.w),
decoration: BoxDecoration(
color: const Color(0xFFDEDEDE), // 半透明底色
borderRadius: BorderRadius.circular(34.r),
border: Border.all(
color: Colors.white.withOpacity(0.2), // 高光边框
width: 1.5,
),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (widget.title != null) ...[
Align(
alignment: Alignment.centerLeft,
child: Text(
widget.title!,
style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
height: 1.3,
),
),
),
SizedBox(height: 4.w),
],
if (widget.message != null || widget.customMessageWidget != null) ...[
Container(
constraints: BoxConstraints(maxHeight: 200.h),
child: SingleChildScrollView(
child: widget.customMessageWidget ??
Text(
widget.message!,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 14.sp,
color: Colors.black,
height: 1.4,
fontFamily: 'AlibabaPuHuiTi-Medium',
),
),
),
),
],
if (widget.confirmText != null || widget.cancelText != null || (widget.confirmText == null && widget.cancelText == null)) ...[
SizedBox(height: 12.w),
if (widget.confirmText == null && widget.cancelText == null)
Center(
child: SizedBox(
width: 85.w,
child: _buildConfirmButton(),
),
)
else
Row(
children: [
if (widget.confirmText != null) Expanded(child: _buildConfirmButton()),
if (widget.cancelText != null && widget.confirmText != null)
SizedBox(width: 12.w),
if (widget.cancelText != null)
Expanded(
child: TextButton(
onPressed: () {
Get.back();
widget.onCancel?.call();
},
style: TextButton.styleFrom(
backgroundColor: const Color(0xFFFF00B7),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(23.r),
),
minimumSize: Size(85.w, 40.w),
padding: EdgeInsets.zero,
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
child: Text(
widget.cancelText!,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
fontFamily: 'AlibabaPuHuiTi-Medium',
),
),
),
),
],
),
]
],
),
),
),
),
),
);
if (widget.preventBackDismiss) {
return WillPopScope(onWillPop: () async => false, child: dialog);
}
return dialog;
}
}