198 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'package:flutter/material.dart';
 | |
| 
 | |
| /// 对话框模式
 | |
| enum DialogMode { text, input }
 | |
| 
 | |
| class CustomAlertDialog extends StatefulWidget {
 | |
|   final String title;
 | |
|   final String content; // 文字模式下显示
 | |
|   final String hintText; // 输入模式下提示
 | |
|   final String cancelText;
 | |
|   final String confirmText;
 | |
|   final VoidCallback? onCancel;
 | |
|   final VoidCallback? onConfirm; // 文字模式回调
 | |
|   final ValueChanged<String>? onInputConfirm; // 输入模式回调
 | |
|   final DialogMode mode; // 新增:对话框模式
 | |
| 
 | |
|   const CustomAlertDialog({
 | |
|     Key? key,
 | |
|     required this.title,
 | |
|     this.content = '',
 | |
|     this.hintText = '',
 | |
|     this.cancelText = '取消',
 | |
|     this.confirmText = '确定',
 | |
|     this.onCancel,
 | |
|     this.onConfirm,
 | |
|     this.onInputConfirm,
 | |
|     this.mode = DialogMode.text, // 默认文字模式
 | |
|   }) : super(key: key);
 | |
| 
 | |
|   @override
 | |
|   _CustomAlertDialogState createState() => _CustomAlertDialogState();
 | |
| }
 | |
| 
 | |
| class _CustomAlertDialogState extends State<CustomAlertDialog> {
 | |
|   late TextEditingController _controller;
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     super.initState();
 | |
|     // 输入模式下初始化 TextField
 | |
|     _controller = TextEditingController();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void dispose() {
 | |
|     _controller.dispose();
 | |
|     super.dispose();
 | |
|   }
 | |
| 
 | |
|   bool get hasCancel => widget.cancelText.trim().isNotEmpty;
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     return Dialog(
 | |
|       backgroundColor: Colors.transparent,
 | |
|       child: Container(
 | |
|         decoration: BoxDecoration(
 | |
|           color: Colors.white,
 | |
|           borderRadius: BorderRadius.circular(5),
 | |
|         ),
 | |
|         child: Column(
 | |
|           mainAxisSize: MainAxisSize.min,
 | |
|           children: [
 | |
|             const SizedBox(height: 20),
 | |
|             Text(
 | |
|               widget.title,
 | |
|               style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
 | |
|               textAlign: TextAlign.center,
 | |
|             ),
 | |
|             const SizedBox(height: 20),
 | |
| 
 | |
|             // ★ 根据 mode 决定展示文字还是输入框 ★
 | |
|             if (widget.mode == DialogMode.text)
 | |
|               Padding(
 | |
|                 padding: const EdgeInsets.symmetric(horizontal: 30),
 | |
|                 child: Text(
 | |
|                   widget.content,
 | |
|                   style: const TextStyle(fontSize: 16, color: Colors.black45),
 | |
|                   textAlign: TextAlign.center,
 | |
|                 ),
 | |
|               )
 | |
|             else
 | |
|               Padding(
 | |
|                 padding: const EdgeInsets.symmetric(horizontal: 20),
 | |
|                 child: TextField(
 | |
|                   controller: _controller,
 | |
| 
 | |
|                   decoration: InputDecoration(
 | |
|                     hintText: widget.hintText,
 | |
|                     border: const OutlineInputBorder(),
 | |
|                     focusedBorder: OutlineInputBorder(
 | |
|                       borderSide: BorderSide(color: Colors.blue, width: 1),
 | |
|                       borderRadius: BorderRadius.circular(4),
 | |
|                     ),
 | |
|                     isDense: true,
 | |
|                     contentPadding: const EdgeInsets.symmetric(
 | |
|                       vertical: 10,
 | |
|                       horizontal: 10,
 | |
|                     ),
 | |
|                   ),
 | |
|                 ),
 | |
|               ),
 | |
| 
 | |
|             const SizedBox(height: 20),
 | |
|             const Divider(height: 1),
 | |
| 
 | |
|             hasCancel
 | |
|                 ? _buildDoubleButtons(context)
 | |
|                 : _buildSingleButton(context),
 | |
|           ],
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildDoubleButtons(BuildContext context) {
 | |
|     return Row(
 | |
|       children: [
 | |
|         // 取消
 | |
|         Expanded(
 | |
|           child: InkWell(
 | |
|             onTap: () {
 | |
|               Navigator.of(context).pop();
 | |
|               widget.onCancel?.call();
 | |
|             },
 | |
|             child: Container(
 | |
|               padding: const EdgeInsets.symmetric(vertical: 12),
 | |
|               alignment: Alignment.center,
 | |
|               child: Text(
 | |
|                 widget.cancelText,
 | |
|                 style: const TextStyle(
 | |
|                   fontWeight: FontWeight.w500,
 | |
|                   color: Colors.black,
 | |
|                   fontSize: 18,
 | |
|                 ),
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|         ),
 | |
| 
 | |
|         Container(width: 1, height: 48, color: Colors.grey[300]),
 | |
| 
 | |
|         // 确定
 | |
|         Expanded(
 | |
|           child: InkWell(
 | |
|             onTap: () {
 | |
|               Navigator.of(context).pop();
 | |
|               if (widget.mode == DialogMode.text) {
 | |
|                 widget.onConfirm?.call();
 | |
|               } else {
 | |
|                 widget.onInputConfirm?.call(_controller.text.trim());
 | |
|               }
 | |
|             },
 | |
|             child: Container(
 | |
|               padding: const EdgeInsets.symmetric(vertical: 12),
 | |
|               alignment: Alignment.center,
 | |
|               child: Text(
 | |
|                 widget.confirmText,
 | |
|                 style: const TextStyle(
 | |
|                   color: Color(0xFF3874F6),
 | |
|                   fontWeight: FontWeight.w500,
 | |
|                   fontSize: 18,
 | |
|                 ),
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|         ),
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   Widget _buildSingleButton(BuildContext context) {
 | |
|     return InkWell(
 | |
|       onTap: () {
 | |
|         Navigator.of(context).pop();
 | |
|         if (widget.mode == DialogMode.text) {
 | |
|           widget.onConfirm?.call();
 | |
|         } else {
 | |
|           widget.onInputConfirm?.call(_controller.text.trim());
 | |
|         }
 | |
|       },
 | |
|       child: Container(
 | |
|         width: double.infinity,
 | |
|         padding: const EdgeInsets.symmetric(vertical: 14),
 | |
|         alignment: Alignment.center,
 | |
|         child: Text(
 | |
|           widget.confirmText,
 | |
|           style: const TextStyle(
 | |
|             color: Color(0xFF3874F6),
 | |
|             fontWeight: FontWeight.w500,
 | |
|             fontSize: 18,
 | |
|           ),
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |