|
|
@ -157,16 +157,14 @@ class TranslationView extends GetView<TranslationController> { |
|
|
return Obx(() { |
|
|
return Obx(() { |
|
|
final itemCount = controller.translationHistory.length; |
|
|
final itemCount = controller.translationHistory.length; |
|
|
|
|
|
|
|
|
// 计算底部内边距,确保内容不会被底部框遮住 |
|
|
|
|
|
final bottomPadding = controller.bottomBarHeight + 20.h; // 使用控制栏高度加上额外间距 |
|
|
|
|
|
|
|
|
|
|
|
return ListView.builder( |
|
|
return ListView.builder( |
|
|
controller: controller.scrollController, |
|
|
controller: controller.scrollController, |
|
|
padding: EdgeInsets.only( |
|
|
padding: EdgeInsets.only( |
|
|
left: 16.w, |
|
|
left: 16.w, |
|
|
right: 16.w, |
|
|
right: 16.w, |
|
|
top: 16.h, |
|
|
top: 16.h, |
|
|
bottom: bottomPadding |
|
|
bottom: 16.h, |
|
|
), |
|
|
), |
|
|
itemCount: itemCount, |
|
|
itemCount: itemCount, |
|
|
itemBuilder: (context, index) { |
|
|
itemBuilder: (context, index) { |
|
|
@ -175,97 +173,77 @@ class TranslationView extends GetView<TranslationController> { |
|
|
|
|
|
|
|
|
// 构建项目widget |
|
|
// 构建项目widget |
|
|
return _buildTranslationItemWidget( |
|
|
return _buildTranslationItemWidget( |
|
|
historyItem.sourceText, |
|
|
context, |
|
|
historyItem.translatedText, |
|
|
historyItem |
|
|
historyItem.isIntermediate, // 如果是中间结果,设置为当前项 |
|
|
|
|
|
item: historyItem, |
|
|
|
|
|
isIntermediate: historyItem.isIntermediate, |
|
|
|
|
|
isDarkMode: isDarkMode, |
|
|
|
|
|
); |
|
|
); |
|
|
}, |
|
|
}, |
|
|
); |
|
|
); |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
Widget _buildTranslationItemWidget( |
|
|
Widget _buildTranslationItemWidget(BuildContext context, TranslationItem item) { |
|
|
String sourceText, |
|
|
return Container( |
|
|
String translatedText, |
|
|
margin: const EdgeInsets.only(bottom: 8), |
|
|
bool isCurrentItem, |
|
|
padding: const EdgeInsets.all(12), |
|
|
{ |
|
|
|
|
|
TranslationItem? item, |
|
|
|
|
|
bool isIntermediate = false, |
|
|
|
|
|
required bool isDarkMode, |
|
|
|
|
|
} |
|
|
|
|
|
) { |
|
|
|
|
|
// 使用AnimatedContainer实现平滑过渡,但恢复原来的视觉样式 |
|
|
|
|
|
return AnimatedContainer( |
|
|
|
|
|
duration: const Duration(milliseconds: 300), |
|
|
|
|
|
curve: Curves.easeInOut, |
|
|
|
|
|
margin: EdgeInsets.only(bottom: 24.h), |
|
|
|
|
|
decoration: BoxDecoration( |
|
|
decoration: BoxDecoration( |
|
|
color: isDarkMode ? AppColors.cardBackground : Colors.grey[100], |
|
|
color: item.isIntermediate |
|
|
borderRadius: BorderRadius.circular(12.r), |
|
|
? Colors.grey.withOpacity(0.1) // 中间结果使用浅灰色底色 |
|
|
|
|
|
: (item.sourceLanguageCode == controller.sourceLanguageCode.value |
|
|
|
|
|
? Theme.of(context).colorScheme.primary.withOpacity(0.08) // 源语言匹配时使用主题色底色 |
|
|
|
|
|
: Theme.of(context).colorScheme.secondary.withOpacity(0.08)), // 否则使用次要色底色 |
|
|
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
|
|
border: Border.all( |
|
|
|
|
|
color: item.isIntermediate |
|
|
|
|
|
? Colors.grey.withOpacity(0.2) |
|
|
|
|
|
: Colors.transparent, |
|
|
|
|
|
width: 1, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
child: Column( |
|
|
child: Column( |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
children: [ |
|
|
children: [ |
|
|
// Source text |
|
|
// 源文本 |
|
|
AnimatedContainer( |
|
|
Text( |
|
|
duration: const Duration(milliseconds: 300), |
|
|
item.sourceText, |
|
|
width: double.infinity, |
|
|
style: TextStyle( |
|
|
padding: EdgeInsets.all(16.r), |
|
|
fontSize: 16, |
|
|
child: Text( |
|
|
color: Theme.of(context).textTheme.bodyLarge?.color, |
|
|
sourceText.isEmpty && isCurrentItem ? '等待语音输入...' : sourceText, |
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
if (item.translatedText.isNotEmpty) ...[ |
|
|
|
|
|
const SizedBox(height: 8), |
|
|
|
|
|
// 翻译文本 |
|
|
|
|
|
Text( |
|
|
|
|
|
item.translatedText, |
|
|
style: TextStyle( |
|
|
style: TextStyle( |
|
|
fontSize: 16.sp, |
|
|
fontSize: 16, |
|
|
color: sourceText.isEmpty && isCurrentItem |
|
|
color: Theme.of(context).textTheme.bodyMedium?.color, |
|
|
? (isDarkMode ? Colors.grey[400] : Colors.grey) |
|
|
fontWeight: FontWeight.w500, |
|
|
: (isDarkMode ? Colors.white : Colors.black), |
|
|
|
|
|
fontWeight: FontWeight.normal, |
|
|
|
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
), |
|
|
], |
|
|
|
|
|
// 语言信息和时间戳 |
|
|
// Divider |
|
|
const SizedBox(height: 4), |
|
|
Divider(height: 1, thickness: 1, color: isDarkMode ? Colors.grey[800] : Colors.grey[200]), |
|
|
Row( |
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween, |
|
|
// Translated text |
|
|
children: [ |
|
|
AnimatedContainer( |
|
|
Text( |
|
|
duration: const Duration(milliseconds: 300), |
|
|
'${item.sourceLanguageName} → ${item.targetLanguageName}', |
|
|
width: double.infinity, |
|
|
style: TextStyle( |
|
|
padding: EdgeInsets.all(16.r), |
|
|
fontSize: 12, |
|
|
child: Row( |
|
|
color: Theme.of(context).textTheme.bodySmall?.color, |
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
|
|
children: [ |
|
|
|
|
|
Expanded( |
|
|
|
|
|
child: Text( |
|
|
|
|
|
translatedText.isEmpty && isCurrentItem ? '翻译结果将显示在这里...' : translatedText, |
|
|
|
|
|
style: TextStyle( |
|
|
|
|
|
fontSize: 16.sp, |
|
|
|
|
|
color: translatedText.isEmpty && isCurrentItem |
|
|
|
|
|
? (isDarkMode ? Colors.grey[400] : Colors.grey) |
|
|
|
|
|
: (isDarkMode ? Colors.white : Colors.black), |
|
|
|
|
|
fontStyle: FontStyle.normal, |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
|
|
|
), |
|
|
), |
|
|
if (translatedText.isNotEmpty) |
|
|
), |
|
|
IconButton( |
|
|
if (!item.isIntermediate) |
|
|
icon: Icon( |
|
|
GestureDetector( |
|
|
Icons.volume_up, |
|
|
onTap: () => controller.playTranslationItem(item), |
|
|
color: isDarkMode ? AppColors.primary : Colors.blue, |
|
|
child: Icon( |
|
|
size: 20.sp, |
|
|
Icons.volume_up, |
|
|
), |
|
|
size: 18, |
|
|
onPressed: () { |
|
|
color: Theme.of(context).colorScheme.primary, |
|
|
if (item != null) { |
|
|
|
|
|
controller.playTranslationItem(item); |
|
|
|
|
|
} else { |
|
|
|
|
|
controller.playTranslatedText(translatedText); |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
), |
|
|
), |
|
|
], |
|
|
), |
|
|
), |
|
|
], |
|
|
), |
|
|
), |
|
|
], |
|
|
], |
|
|
), |
|
|
), |
|
|
|