Browse Source

feat: 优化翻译功能交互体验和UI细节

1. 在设置语言时增加重复设置检查,避免不必要的操作
2. 调整翻译结果展示页面的UI布局和样式
3. 为图片翻译结果添加点击放大查看功能
4. 优化文本翻译页面的键盘交互行为
5. 统一调整snackbar显示时长为1秒
newdev_shunjiawei
lxm 12 months ago
parent
commit
682fed342a
  1. 27
      lib/modules/picture_translation/views/picture_translation_view.dart
  2. 7
      lib/modules/settings/controllers/settings_controller.dart
  3. 8
      lib/modules/text_translation/controllers/text_translation_controller.dart
  4. 233
      lib/modules/text_translation/views/text_translation_view.dart
  5. 3
      lib/modules/translation/middleware/controllers/translation_middleware_controller.dart

27
lib/modules/picture_translation/views/picture_translation_view.dart

@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:photo_view/photo_view.dart'; // 新增:图片查看器
import '../controllers/picture_translation_controller.dart'; import '../controllers/picture_translation_controller.dart';
import '../models/picture_translation_models.dart'; import '../models/picture_translation_models.dart';
@ -515,13 +516,17 @@ class PictureTranslationView extends GetView<PictureTranslationController> {
SizedBox(height: 8.h), SizedBox(height: 8.h),
Container( Container(
height: 200.h, height: 200.h,
margin: EdgeInsets.symmetric(horizontal: 16.w) margin:
.copyWith(bottom: 16.h), EdgeInsets.symmetric(horizontal: 16.w).copyWith(bottom: 16.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.grey[100], color: Colors.grey[100],
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
border: Border.all(color: Colors.grey[300]!), border: Border.all(color: Colors.grey[300]!),
), ),
child: GestureDetector(
onTap: () => _openImageViewer(
MemoryImage(controller.translatedImageBytes.value!),
),
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
child: Image.memory( child: Image.memory(
@ -548,6 +553,7 @@ class PictureTranslationView extends GetView<PictureTranslationController> {
), ),
), ),
), ),
),
], ],
], ],
), ),
@ -972,3 +978,20 @@ class PictureTranslationView extends GetView<PictureTranslationController> {
); );
} }
} }
void _openImageViewer(ImageProvider provider) {
Get.to(() => Scaffold(
body: Container(
color: Colors.black,
child: GestureDetector(
onTap: () => Get.back(), // 点击退出
child: PhotoView(
imageProvider: provider,
minScale: PhotoViewComputedScale.contained,
maxScale: PhotoViewComputedScale.covered * 2,
backgroundDecoration: const BoxDecoration(color: Colors.black),
),
),
),
));
}

7
lib/modules/settings/controllers/settings_controller.dart

@ -305,6 +305,13 @@ class SettingsController extends GetxController {
/// 设置语言 /// 设置语言
Future<void> setLanguage(LanguageModel data) async { Future<void> setLanguage(LanguageModel data) async {
try { try {
// 如果用户选择的语言与当前语言一致,则直接返回,避免重复设置
// print('lxm--设置语言: ${data.value}');
// print('lxm--当前语言: ${language.value.value}');
if (data.value == language.value.value) {
return;
}
Locale? targetLocale; Locale? targetLocale;
// print('lxm--设置语言: ${data.value}'); // print('lxm--设置语言: ${data.value}');

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

@ -308,7 +308,7 @@ class TextTranslationController extends GetxController {
snackPosition: SnackPosition.TOP, snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withOpacity(0.9), backgroundColor: Colors.green.withOpacity(0.9),
colorText: Colors.white, colorText: Colors.white,
duration: const Duration(seconds: 2), duration: const Duration(seconds: 1),
); );
} }
} }
@ -397,8 +397,7 @@ class TextTranslationController extends GetxController {
decoration: BoxDecoration( decoration: BoxDecoration(
color: isSelected color: isSelected
? (isDarkMode ? (isDarkMode
? const Color(0xFF6200EE) ? const Color(0xFF6200EE).withOpacity(0.2)
.withOpacity(0.2)
: Colors.blue.withOpacity(0.1)) : Colors.blue.withOpacity(0.1))
: (isDarkMode : (isDarkMode
? Colors.white.withOpacity(0.05) ? Colors.white.withOpacity(0.05)
@ -472,8 +471,7 @@ class TextTranslationController extends GetxController {
child: Text( child: Text(
'cancel'.tr, // 翻译键代表的中文文本内容 'cancel'.tr, // 翻译键代表的中文文本内容
style: TextStyle( style: TextStyle(
color: color: isDarkMode ? const Color(0xFF6200EE) : Colors.blue,
isDarkMode ? const Color(0xFF6200EE) : Colors.blue,
), ),
), ),
), ),

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

@ -16,8 +16,16 @@ class TextTranslationView extends GetView<TextTranslationController> {
return Scaffold( return Scaffold(
backgroundColor: isDarkMode ? Colors.black : Colors.grey[50], backgroundColor: isDarkMode ? Colors.black : Colors.grey[50],
appBar: _buildAppBar(isDarkMode), appBar: _buildAppBar(isDarkMode),
body: SafeArea( body: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
// 点击空白区域收起键盘
FocusManager.instance.primaryFocus?.unfocus();
},
child: SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
// 拖动时也自动收起键盘
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
padding: EdgeInsets.all(16.w), padding: EdgeInsets.all(16.w),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -36,14 +44,15 @@ class TextTranslationView extends GetView<TextTranslationController> {
), ),
), ),
), ),
),
); );
} }
/// 构建应用栏 /// 构建应用栏
PreferredSizeWidget _buildAppBar(bool isDarkMode) { PreferredSizeWidget _buildAppBar(bool isDarkMode) {
return AppBar( return AppBar(
backgroundColor: isDarkMode ? Colors.black : Colors.white, backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
elevation: 0, elevation: 1,
leading: IconButton( leading: IconButton(
icon: Icon( icon: Icon(
Icons.arrow_back_ios, Icons.arrow_back_ios,
@ -54,23 +63,26 @@ class TextTranslationView extends GetView<TextTranslationController> {
), ),
centerTitle: true, centerTitle: true,
title: Text( title: Text(
'textTranslation'.tr, 'textTranslation'.tr, // 文本翻译
style: TextStyle( style: TextStyle(
fontSize: 18.sp, fontSize: 18.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black, color: isDarkMode ? Colors.white : Colors.black,
), ),
), overflow: TextOverflow.ellipsis,
actions: [ maxLines: 1,
IconButton( ),
icon: Icon( // actions: [
Icons.clear_all, // IconButton(
color: isDarkMode ? Colors.white : Colors.black, // icon: Icon(
), // Icons.clear_all,
onPressed: controller.clearInput, // color: isDarkMode ? Colors.white : Colors.black,
tooltip: 'clearInput'.tr, // size: 24.sp,
), // ),
], // onPressed: controller.clearInput,
// tooltip: 'clearInput'.tr,
// ),
// ],
bottom: PreferredSize( bottom: PreferredSize(
preferredSize: Size.fromHeight(50.h), preferredSize: Size.fromHeight(50.h),
child: Padding( child: Padding(
@ -83,25 +95,7 @@ class TextTranslationView extends GetView<TextTranslationController> {
/// 构建语言选择器(统一与其它翻译模式的样式) /// 构建语言选择器(统一与其它翻译模式的样式)
Widget _buildLanguageSelector(bool isDarkMode) { Widget _buildLanguageSelector(bool isDarkMode) {
return Container( return Row(
height: 44.h,
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 6.h),
decoration: BoxDecoration(
color: isDarkMode ? AppColors.cardBackground : Colors.white,
boxShadow: [
BoxShadow(
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: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// 源语言选择(与面对面模式一致的胶囊样式) // 源语言选择(与面对面模式一致的胶囊样式)
@ -178,59 +172,6 @@ class TextTranslationView extends GetView<TextTranslationController> {
), ),
), ),
], ],
),
);
}
/// 构建语言选择按钮
Widget _buildLanguageButton({
required String label,
required String selectedLanguage,
required VoidCallback onTap,
required bool isDarkMode,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[100],
borderRadius: BorderRadius.circular(8.r),
border: Border.all(
color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: TextStyle(
fontSize: 12.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
),
SizedBox(height: 4.h),
Text(
selectedLanguage,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
color: isDarkMode ? Colors.white : Colors.black,
),
),
],
),
Icon(
Icons.keyboard_arrow_down,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
],
),
),
); );
} }
@ -248,53 +189,60 @@ class TextTranslationView extends GetView<TextTranslationController> {
), ),
], ],
), ),
child: Column( child:
crossAxisAlignment: CrossAxisAlignment.start, // Column(
children: [ //crossAxisAlignment: CrossAxisAlignment.start,
Padding( // children: [
padding: EdgeInsets.fromLTRB(16.w, 16.h, 16.w, 8.h), // Padding(
child: Text( // padding: EdgeInsets.fromLTRB(16.w, 16.h, 16.w, 8.h),
'inputTextToTranslate'.tr, // child: Text(
style: TextStyle( // 'inputTextToTranslate'.tr,
fontSize: 14.sp, // style: TextStyle(
fontWeight: FontWeight.w500, // fontSize: 14.sp,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700], // fontWeight: FontWeight.w500,
), // color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
), // ),
), // ),
// ),
Container( Container(
margin: EdgeInsets.symmetric(horizontal: 16.w), //margin: EdgeInsets.symmetric(horizontal: 16.w),
padding: EdgeInsets.all(12.w), padding: EdgeInsets.all(12.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[50], color: isDarkMode ? Colors.grey[800] : Colors.grey[50],
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(12.r),
border: Border.all( border: Border.all(
color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!, color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!,
), ),
), ),
child: TextField( child: TextField(
controller: controller.textController, controller: controller.textController,
maxLines: 6, maxLines: 7,
maxLength: 1000, maxLength: 1000,
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 14.sp,
color: isDarkMode ? Colors.white : Colors.black, color: isDarkMode ? Colors.white : Colors.black,
height: 1.5.h,
), ),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'inputTextToTranslate'.tr, hintText: 'inputTextToTranslate'.tr, // 请输入待翻译的文本
hintStyle: TextStyle( hintStyle: TextStyle(
color: isDarkMode ? Colors.grey[500] : Colors.grey[400], color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
), ),
border: InputBorder.none, border: InputBorder.none,
focusedBorder: InputBorder.none,
counterStyle: TextStyle( counterStyle: TextStyle(
color: isDarkMode ? Colors.grey[500] : Colors.grey[400], color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
), ),
filled: true,
fillColor: isDarkMode ? Colors.grey[800] : Colors.grey[50],
contentPadding: EdgeInsets.symmetric(horizontal: 0, vertical: 0.h),
isDense: true, // 减少默认边距
), ),
), ),
), ),
SizedBox(height: 16.h), //SizedBox(height: 16.h),
], // ],
), // ),
); );
} }
@ -305,7 +253,11 @@ class TextTranslationView extends GetView<TextTranslationController> {
child: ElevatedButton( child: ElevatedButton(
onPressed: controller.isTranslating.value onPressed: controller.isTranslating.value
? null ? null
: controller.translateText, : () {
// 点击“翻译”按钮时先收起键盘
FocusManager.instance.primaryFocus?.unfocus();
controller.translateText();
},
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
foregroundColor: Colors.white, foregroundColor: Colors.white,
@ -331,7 +283,7 @@ class TextTranslationView extends GetView<TextTranslationController> {
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
Text( Text(
'translating'.tr, 'translating'.tr, // 正在翻译
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -340,7 +292,7 @@ class TextTranslationView extends GetView<TextTranslationController> {
], ],
) )
: Text( : Text(
'translate'.tr, 'translate'.tr, // 翻译
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -359,7 +311,7 @@ class TextTranslationView extends GetView<TextTranslationController> {
return Container( return Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.all(16.w), // padding: EdgeInsets.all(16.w),
decoration: BoxDecoration( decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[900] : Colors.white, color: isDarkMode ? Colors.grey[900] : Colors.white,
borderRadius: BorderRadius.circular(12.r), borderRadius: BorderRadius.circular(12.r),
@ -374,22 +326,35 @@ class TextTranslationView extends GetView<TextTranslationController> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Container(
mainAxisAlignment: MainAxisAlignment.spaceBetween, width: double.infinity,
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[50],
borderRadius: BorderRadius.circular(8.r),
border: Border.all(
color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!,
),
),
child: Column(
children: [ children: [
Text( Text(
'translationResult'.tr, controller.translatedText.value,
style: TextStyle( style: TextStyle(
fontSize: 14.sp, fontSize: 14.sp,
fontWeight: FontWeight.w500, color: isDarkMode ? Colors.white : Colors.black,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700], height: 1.5.h,
), ),
), ),
SizedBox(height: 12.h),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector( GestureDetector(
onTap: controller.copyResult, onTap: controller.copyResult,
child: Container( child: Container(
padding: padding: EdgeInsets.symmetric(
EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h), horizontal: 12.w, vertical: 6.h),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1), color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(6.r), borderRadius: BorderRadius.circular(6.r),
@ -402,39 +367,13 @@ class TextTranslationView extends GetView<TextTranslationController> {
size: 16.sp, size: 16.sp,
color: Colors.blue, color: Colors.blue,
), ),
SizedBox(width: 4.w),
Text(
'copyResult'.tr,
style: TextStyle(
fontSize: 12.sp,
color: Colors.blue,
fontWeight: FontWeight.w500,
),
),
], ],
), ),
), ),
), ),
], ],
), ),
SizedBox(height: 12.h), ],
Container(
width: double.infinity,
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[50],
borderRadius: BorderRadius.circular(8.r),
border: Border.all(
color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!,
),
),
child: Text(
controller.translatedText.value,
style: TextStyle(
fontSize: 16.sp,
color: isDarkMode ? Colors.white : Colors.black,
height: 1.5,
),
), ),
), ),
], ],

3
lib/modules/translation/middleware/controllers/translation_middleware_controller.dart

@ -66,7 +66,8 @@ class TranslationMiddlewareController extends GetxController {
// 翻译键代表的中文文本内容 // 翻译键代表的中文文本内容
Get.snackbar('connectDevice'.tr, Get.snackbar('connectDevice'.tr,
'pleaseConnectDeepSoundDevice'.tr, // 连接设备 / 请连接 Voitrans 设备 'pleaseConnectDeepSoundDevice'.tr, // 连接设备 / 请连接 Voitrans 设备
snackPosition: SnackPosition.TOP); snackPosition: SnackPosition.TOP,
duration: const Duration(seconds: 1));
//EasyLoading.showInfo('connectDevice'.tr); //EasyLoading.showInfo('connectDevice'.tr);
return; return;
} }

Loading…
Cancel
Save