You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
9.6 KiB
212 lines
9.6 KiB
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import '../../controllers/translation_controller.dart';
|
|
|
|
/// 语言选择对话框
|
|
class LanguageSelectionDialog {
|
|
/// 显示语言选择对话框(通用,支持文本/图片/语音翻译)
|
|
/// [isSource] 是否为源语言选择
|
|
/// [isDarkMode] 深色模式标记
|
|
/// [languages] 可选,自定义语言列表(中文名称列表);若为空则使用语音翻译模块的列表
|
|
/// [currentLanguage] 当前选中的语言中文名称
|
|
/// [includeAutoDetect] 是否在源语言首项加入“自动检测”选项(仅文本翻译需要)
|
|
/// [translateLanguageNames] 是否将语言名称作为翻译键进行翻译(语音翻译保持原逻辑)
|
|
/// [onSelected] 选中项回调,参数为中文名称
|
|
static void show(
|
|
bool isSource,
|
|
bool isDarkMode, {
|
|
List<String>? languages,
|
|
String? currentLanguage,
|
|
bool includeAutoDetect = false,
|
|
bool translateLanguageNames = true,
|
|
ValueChanged<String>? onSelected,
|
|
}) {
|
|
// 若未提供自定义列表,则在已注册时回退到语音翻译控制器的列表
|
|
final hasTranslationController = Get.isRegistered<TranslationController>();
|
|
final TranslationController? controller =
|
|
hasTranslationController ? Get.find<TranslationController>() : null;
|
|
final fallbackLanguages =
|
|
controller?.supportedLanguages.keys.toList() ?? <String>[]; // 中文名称列表
|
|
|
|
final displayLanguages = List<String>.from(languages ?? fallbackLanguages);
|
|
|
|
// 源语言是否展示“自动检测”选项(仅列表显示,值为中文“自动检测”)
|
|
final hasAutoDetect = includeAutoDetect && isSource;
|
|
|
|
// 计算当前选中项(优先传入值,其次回退到语音翻译控制器,最后列表首项或自动检测)
|
|
final selectedLanguage = currentLanguage ??
|
|
(controller != null
|
|
? (isSource
|
|
? controller.sourceLanguage.value
|
|
: controller.targetLanguage.value)
|
|
: (hasAutoDetect
|
|
? 'autoDetect'
|
|
: (displayLanguages.isNotEmpty ? displayLanguages.first : '')));
|
|
|
|
Get.dialog(Dialog(
|
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16.r), // 统一圆角尺寸为16
|
|
),
|
|
alignment: isSource ? Alignment.centerLeft : Alignment.centerRight,
|
|
insetPadding: EdgeInsets.symmetric(horizontal: 10.w),
|
|
child: SizedBox(
|
|
width: 0.4.sw,
|
|
child: Padding(
|
|
// 使用Padding替代Container的padding
|
|
padding: EdgeInsets.all(12.w), // 统一内边距
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 标题区域
|
|
Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 8.w),
|
|
child: Text(
|
|
isSource
|
|
? 'selectSourceLanguage'.tr // 选择源语言
|
|
: 'selectTargetLanguage'.tr, // 选择目标语言
|
|
style: TextStyle(
|
|
fontSize: 18.sp, // 调整字号
|
|
fontWeight: FontWeight.w600, // 使用数字字重
|
|
color: isDarkMode ? Colors.white : Colors.black87, // 优化文本颜色
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 16.h),
|
|
|
|
// 语言列表区域
|
|
Container(
|
|
constraints: BoxConstraints(maxHeight: 0.5.sh),
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: List.generate(
|
|
hasAutoDetect
|
|
? (displayLanguages.length + 1)
|
|
: displayLanguages.length,
|
|
(index) {
|
|
// 构造展示与实际值
|
|
final isAutoDetectItem = hasAutoDetect && index == 0;
|
|
final valueText = isAutoDetectItem
|
|
? 'autoDetect'.tr
|
|
: displayLanguages[
|
|
hasAutoDetect ? index - 1 : index];
|
|
final displayText = isAutoDetectItem
|
|
? 'autoDetect'.tr // 自动检测
|
|
: (translateLanguageNames
|
|
? valueText.tr
|
|
: valueText);
|
|
|
|
final isSelected = selectedLanguage == valueText;
|
|
|
|
return GestureDetector(
|
|
// 改用手势检测器实现点击
|
|
onTap: () {
|
|
if (onSelected != null) {
|
|
onSelected(valueText);
|
|
} else {
|
|
// 默认行为:语音翻译控制器设置语言
|
|
if (isSource) {
|
|
controller?.setSourceLanguage(valueText);
|
|
} else {
|
|
controller?.setTargetLanguage(valueText);
|
|
}
|
|
}
|
|
Get.back();
|
|
},
|
|
child: Container(
|
|
margin: EdgeInsets.only(bottom: 10.h), // 添加项间距
|
|
padding: EdgeInsets.all(10.w), // 统一内边距
|
|
decoration: BoxDecoration(
|
|
color: isSelected // 选中状态背景色
|
|
? (isDarkMode
|
|
? const Color(0xFF6200EE).withOpacity(0.2)
|
|
: Colors.blue.withOpacity(0.1))
|
|
: (isDarkMode // 未选中状态背景色
|
|
? Colors.white.withOpacity(0.05)
|
|
: Colors.grey[200]!),
|
|
borderRadius: BorderRadius.circular(12.r), // 项圆角
|
|
border: Border.all(
|
|
// 选中状态边框
|
|
color: isSelected
|
|
? (isDarkMode
|
|
? const Color(0xFF6200EE)
|
|
: Colors.blue)
|
|
: (isDarkMode // 未选中状态背景色
|
|
? Colors.white.withOpacity(0.05)
|
|
: Colors.grey[200]!),
|
|
width: 1,
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
// 语言名称
|
|
Expanded(
|
|
child: Text(
|
|
displayText,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.w500,
|
|
color: isDarkMode
|
|
? Colors.white
|
|
: Colors.black87,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
),
|
|
// 选中指示器
|
|
Container(
|
|
width: 24.w,
|
|
height: 24.w,
|
|
decoration: BoxDecoration(
|
|
color: isSelected // 动态颜色
|
|
? (isDarkMode
|
|
? const Color(0xFF6200EE)
|
|
: Colors.blue)
|
|
: (isDarkMode
|
|
? Colors.white.withOpacity(0.1)
|
|
: Colors.grey[300]),
|
|
shape: BoxShape.circle, // 圆形样式
|
|
),
|
|
child: isSelected
|
|
? Icon(
|
|
// 选中时显示对勾
|
|
Icons.check,
|
|
size: 16.w,
|
|
color: Colors.white,
|
|
)
|
|
: null,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(height: 16.h),
|
|
|
|
// 取消按钮
|
|
Align(
|
|
alignment: Alignment.centerRight,
|
|
child: TextButton(
|
|
onPressed: () => Get.back(),
|
|
child: Text(
|
|
'cancel'.tr, // 取消
|
|
style: TextStyle(
|
|
color: isDarkMode ? const Color(0xFF6200EE) : Colors.blue,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
));
|
|
}
|
|
}
|
|
|