|
|
|
@ -109,7 +109,6 @@ class TranslationView extends GetView<TranslationController> { |
|
|
|
)), |
|
|
|
centerTitle: true, |
|
|
|
actions: [ |
|
|
|
|
|
|
|
Obx(() { |
|
|
|
if (controller.isRecording.value) { |
|
|
|
// 录音中:显示红色计时器样式,点击可停止录音 |
|
|
|
@ -305,7 +304,8 @@ class TranslationView extends GetView<TranslationController> { |
|
|
|
itemCount: itemCount, |
|
|
|
itemBuilder: (context, index) { |
|
|
|
// 如果是最后一项且有更多历史记录,显示加载指示器(reverse模式下) |
|
|
|
if (index == controller.translationHistory.length && controller.hasMoreHistory.value) { |
|
|
|
if (index == controller.translationHistory.length && |
|
|
|
controller.hasMoreHistory.value) { |
|
|
|
return _buildLoadMoreIndicator(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -313,7 +313,8 @@ class TranslationView extends GetView<TranslationController> { |
|
|
|
final historyIndex = controller.translationHistory.length - 1 - index; |
|
|
|
|
|
|
|
// 检查索引是否有效(reverse模式下的索引验证) |
|
|
|
if (historyIndex < 0 || historyIndex >= controller.translationHistory.length) { |
|
|
|
if (historyIndex < 0 || |
|
|
|
historyIndex >= controller.translationHistory.length) { |
|
|
|
return const SizedBox.shrink(); |
|
|
|
} |
|
|
|
|
|
|
|
@ -668,148 +669,153 @@ class TranslationView extends GetView<TranslationController> { |
|
|
|
|
|
|
|
// 显示语言选择对话框 |
|
|
|
void _showLanguageSelectionDialog(bool isSource, bool isDarkMode) { |
|
|
|
Get.dialog( |
|
|
|
Dialog( |
|
|
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16.r), // 统一圆角尺寸为16 |
|
|
|
), |
|
|
|
insetPadding: EdgeInsets.symmetric(horizontal: 20.w), |
|
|
|
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, // 优化文本颜色 |
|
|
|
Get.dialog( |
|
|
|
Dialog( |
|
|
|
backgroundColor: isDarkMode ? Colors.grey[900] : Colors.white, |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(16.r), // 统一圆角尺寸为16 |
|
|
|
), |
|
|
|
insetPadding: EdgeInsets.symmetric(horizontal: 20.w), |
|
|
|
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: controller.supportedLanguages.keys.map((language) { |
|
|
|
return Obx(() { |
|
|
|
final currentLanguage = isSource |
|
|
|
? controller.sourceLanguage.value |
|
|
|
: controller.targetLanguage.value; |
|
|
|
final isSelected = currentLanguage == language; |
|
|
|
|
|
|
|
return GestureDetector( // 改用手势检测器实现点击 |
|
|
|
onTap: () { |
|
|
|
if (isSource) { |
|
|
|
controller.setSourceLanguage(language); |
|
|
|
} else { |
|
|
|
controller.setTargetLanguage(language); |
|
|
|
} |
|
|
|
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, |
|
|
|
SizedBox(height: 16.h), |
|
|
|
|
|
|
|
// 语言列表区域 |
|
|
|
Container( |
|
|
|
constraints: BoxConstraints(maxHeight: 0.5.sh), |
|
|
|
child: SingleChildScrollView( |
|
|
|
child: Column( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: |
|
|
|
controller.supportedLanguages.keys.map((language) { |
|
|
|
return Obx(() { |
|
|
|
final currentLanguage = isSource |
|
|
|
? controller.sourceLanguage.value |
|
|
|
: controller.targetLanguage.value; |
|
|
|
final isSelected = currentLanguage == language; |
|
|
|
|
|
|
|
return GestureDetector( |
|
|
|
// 改用手势检测器实现点击 |
|
|
|
onTap: () { |
|
|
|
if (isSource) { |
|
|
|
controller.setSourceLanguage(language); |
|
|
|
} else { |
|
|
|
controller.setTargetLanguage(language); |
|
|
|
} |
|
|
|
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( |
|
|
|
language.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white |
|
|
|
: Colors.black87, |
|
|
|
overflow: TextOverflow.ellipsis, |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
// 语言名称 |
|
|
|
Expanded( |
|
|
|
child: Text( |
|
|
|
language.tr, |
|
|
|
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, // 圆形样式 |
|
|
|
// 选中指示器 |
|
|
|
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, |
|
|
|
), |
|
|
|
child: isSelected |
|
|
|
? Icon( // 选中时显示对勾 |
|
|
|
Icons.check, |
|
|
|
size: 16.w, |
|
|
|
color: Colors.white, |
|
|
|
) |
|
|
|
: null, |
|
|
|
), |
|
|
|
], |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
}); |
|
|
|
}).toList(), |
|
|
|
); |
|
|
|
}); |
|
|
|
}).toList(), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
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, |
|
|
|
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, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
// 构建加载更多指示器 |
|
|
|
Widget _buildLoadMoreIndicator() { |
|
|
|
@ -853,7 +859,8 @@ class TranslationView extends GetView<TranslationController> { |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () => controller.loadMoreHistory(), |
|
|
|
child: Container( |
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), |
|
|
|
padding: |
|
|
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 8), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.red[50], |
|
|
|
borderRadius: BorderRadius.circular(20), |
|
|
|
|