Browse Source

refactor(文本翻译): 重构语言选择器样式与对话框布局

- 将语言选择器移至AppBar底部并统一胶囊样式
- 重写语言选择对话框为侧边弹出样式
- 使用统一颜色主题和圆角尺寸
- 优化暗黑模式下的显示效果
weicu
lxm 12 months ago
parent
commit
6e6bc08df6
  1. 221
      lib/modules/text_translation/controllers/text_translation_controller.dart
  2. 128
      lib/modules/text_translation/views/text_translation_view.dart

221
lib/modules/text_translation/controllers/text_translation_controller.dart

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../data/services/volcano_translation_service.dart';
import '../../../data/services/language_manager.dart';
@ -318,75 +319,169 @@ class TextTranslationController extends GetxController {
translatedText.value = '';
}
/// 显示语言选择对话框
/// 显示语言选择对话框(统一与其它翻译模式的样式)
void showLanguageSelector({required bool isSourceLanguage}) {
Get.bottomSheet(
Container(
height: Get.height * 0.6,
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
isSourceLanguage
? 'sourceLanguage'.tr
: 'targetLanguage'.tr,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
final isDarkMode = Theme.of(Get.context!).brightness == Brightness.dark;
Get.dialog(Dialog(
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r), // 统一圆角尺寸
),
alignment:
isSourceLanguage ? Alignment.centerLeft : Alignment.centerRight,
insetPadding: EdgeInsets.symmetric(horizontal: 10.w),
child: SizedBox(
width: 0.4.sw,
child: Padding(
padding: EdgeInsets.all(12.w),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 标题区域
Padding(
padding: EdgeInsets.symmetric(horizontal: 8.w),
child: Text(
isSourceLanguage
? 'selectSourceLanguage'.tr // 翻译键代表的中文文本内容
: 'selectTargetLanguage'.tr, // 翻译键代表的中文文本内容
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black87,
),
IconButton(
onPressed: () => Get.back(),
icon: const Icon(Icons.close),
),
),
SizedBox(height: 16.h),
// 语言列表区域
Container(
constraints: BoxConstraints(maxHeight: 0.5.sh),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(
isSourceLanguage
? (supportedLanguages.length + 1)
: supportedLanguages.length,
(index) {
// 源语言下首项为“自动检测”
final displayText = isSourceLanguage && index == 0
? 'autoDetect'.tr // 翻译键代表的中文文本内容
: (isSourceLanguage
? supportedLanguages[index - 1]
: supportedLanguages[index]);
final valueText = isSourceLanguage && index == 0
? '自动检测'
: (isSourceLanguage
? supportedLanguages[index - 1]
: supportedLanguages[index]);
final isSelected = isSourceLanguage
? valueText == sourceLanguageChineseName.value
: valueText == targetLanguageChineseName.value;
return GestureDetector(
onTap: () {
if (isSourceLanguage) {
setSourceLanguage(valueText);
} else {
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,
),
],
),
),
);
},
),
),
],
),
),
),
const Divider(height: 1),
Expanded(
child: ListView.builder(
itemCount: (isSourceLanguage
? (supportedLanguages.length + 1)
: supportedLanguages.length),
itemBuilder: (context, index) {
final language = isSourceLanguage
? (index == 0
? '自动检测'
: supportedLanguages[index - 1])
: supportedLanguages[index];
final isSelected = isSourceLanguage
? language == sourceLanguageChineseName.value
: language == targetLanguageChineseName.value;
return ListTile(
title: Text(language),
trailing: isSelected
? const Icon(Icons.check, color: Colors.blue)
: null,
onTap: () {
if (isSourceLanguage) {
setSourceLanguage(language);
} else {
setTargetLanguage(language);
}
Get.back();
},
);
},
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,
),
),
),
),
),
],
],
),
),
),
isScrollControlled: true,
);
));
}
}

128
lib/modules/text_translation/views/text_translation_view.dart

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../../core/theme/app_colors.dart';
import '../controllers/text_translation_controller.dart';
@ -21,10 +22,6 @@ class TextTranslationView extends GetView<TextTranslationController> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 语言选择区域
_buildLanguageSelector(isDarkMode),
SizedBox(height: 20.h),
// 输入区域
_buildInputSection(isDarkMode),
SizedBox(height: 20.h),
@ -74,67 +71,112 @@ class TextTranslationView extends GetView<TextTranslationController> {
tooltip: 'clearInput'.tr,
),
],
bottom: PreferredSize(
preferredSize: Size.fromHeight(50.h),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
child: _buildLanguageSelector(isDarkMode),
),
),
);
}
/// 构建语言选择器
/// 构建语言选择器(统一与其它翻译模式的样式)
Widget _buildLanguageSelector(bool isDarkMode) {
return Container(
padding: EdgeInsets.all(16.w),
height: 44.h,
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 6.h),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[900] : Colors.white,
borderRadius: BorderRadius.circular(12.r),
color: isDarkMode ? AppColors.cardBackground : Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, 2),
),
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, -2),
),
],
),
child: Column(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 源语言选择
Obx(() => _buildLanguageButton(
label: 'sourceLanguage'.tr,
selectedLanguage: controller.sourceLanguageChineseName.value,
onTap: () =>
controller.showLanguageSelector(isSourceLanguage: true),
isDarkMode: isDarkMode,
)),
SizedBox(height: 12.h),
// 交换语言按钮
Center(
// 源语言选择(与面对面模式一致的胶囊样式)
Expanded(
child: GestureDetector(
onTap: controller.swapLanguages,
onTap: () =>
controller.showLanguageSelector(isSourceLanguage: true),
child: Container(
width: 40.w,
height: 40.w,
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(
Icons.swap_vert,
color: Colors.blue,
size: 20.sp,
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[100],
borderRadius: BorderRadius.circular(16.r),
),
child: Obx(() => Text(
controller.sourceLanguageChineseName.value,
style: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
)),
),
),
),
SizedBox(height: 12.h),
// 语言互换按钮(统一样式与颜色)
GestureDetector(
onTap: controller.swapLanguages,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 8.w),
padding: EdgeInsets.all(4.r),
decoration: BoxDecoration(
color: isDarkMode
? AppColors.primary.withOpacity(0.2)
: Colors.blue[50],
shape: BoxShape.circle,
),
child: Icon(
Icons.swap_horiz,
color: isDarkMode ? AppColors.primary : Colors.blue,
size: 20.sp,
),
),
),
// 目标语言选择
Obx(() => _buildLanguageButton(
label: 'targetLanguage'.tr,
selectedLanguage: controller.targetLanguageChineseName.value,
onTap: () =>
controller.showLanguageSelector(isSourceLanguage: false),
isDarkMode: isDarkMode,
)),
// 目标语言选择(与面对面模式一致的胶囊样式)
Expanded(
child: GestureDetector(
onTap: () =>
controller.showLanguageSelector(isSourceLanguage: false),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
decoration: BoxDecoration(
color: isDarkMode
? Colors.white.withOpacity(0.1)
: Colors.grey[100],
borderRadius: BorderRadius.circular(16.r),
),
child: Obx(() => Text(
controller.targetLanguageChineseName.value,
style: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
)),
),
),
),
],
),
);

Loading…
Cancel
Save