Browse Source

修改背景动画

newdev_shunjiawei
tanlongsheng 2 years ago
parent
commit
e3bdaa3e56
  1. 10
      lib/modules/chat/controllers/chat_controller.dart
  2. 65
      lib/modules/chat/views/animated_gradient_background.dart
  3. 79
      lib/modules/chat/views/chat_view.dart

10
lib/modules/chat/controllers/chat_controller.dart

@ -96,6 +96,9 @@ class ChatController extends GetxController {
final RxBool isHoldSpeak = false.obs; final RxBool isHoldSpeak = false.obs;
String finalResult = ''; String finalResult = '';
// 按住说话防抖
Timer? _talkDebounceTimer;
@override @override
Future<void> onInit() async { Future<void> onInit() async {
super.onInit(); super.onInit();
@ -289,6 +292,7 @@ class ChatController extends GetxController {
_voiceInteractionSubscription?.cancel(); _voiceInteractionSubscription?.cancel();
_autoStopTimer?.cancel(); _autoStopTimer?.cancel();
_scrollDebounceTimer?.cancel(); // 清理防抖计时器 _scrollDebounceTimer?.cancel(); // 清理防抖计时器
_talkDebounceTimer?.cancel();
_amapFlutter.dispose(); _amapFlutter.dispose();
_locationStream?.cancel(); _locationStream?.cancel();
@ -578,12 +582,15 @@ class ChatController extends GetxController {
// 按下开始说话 // 按下开始说话
void talkLongPress() async { void talkLongPress() async {
_talkDebounceTimer?.cancel();
if (isHoldSpeak.value) return; if (isHoldSpeak.value) return;
_voiceInteractionService.pauseVoiceInteraction(); _voiceInteractionService.pauseVoiceInteraction();
try { try {
final recognitionStream = await _asrService.startContinuousRecognition(); final recognitionStream = await _asrService.startContinuousRecognition();
await Future.delayed(const Duration(milliseconds: 150));
isHoldSpeak.value = true; isHoldSpeak.value = true;
recognizedText.value = ''; recognizedText.value = '';
finalResult = ''; finalResult = '';
@ -601,6 +608,8 @@ class ChatController extends GetxController {
// 松开停止说话 // 松开停止说话
void talkLongPressUp() async { void talkLongPressUp() async {
_talkDebounceTimer?.cancel();
_talkDebounceTimer = Timer(const Duration(milliseconds: 200), () async {
if (!isHoldSpeak.value) return; if (!isHoldSpeak.value) return;
try { try {
await _asrService.stopContinuousRecognition(); await _asrService.stopContinuousRecognition();
@ -621,6 +630,7 @@ class ChatController extends GetxController {
} catch (e) { } catch (e) {
Logger.error('停止语音识别失败', e); Logger.error('停止语音识别失败', e);
} }
});
} }
// 开始语音识别 // 开始语音识别

65
lib/modules/chat/views/animated_gradient_background.dart

@ -0,0 +1,65 @@
import 'package:flutter/material.dart';
class AnimatedGradientBackground extends StatefulWidget {
const AnimatedGradientBackground({super.key});
@override
State<AnimatedGradientBackground> createState() =>
_AnimatedGradientBackgroundState();
}
class _AnimatedGradientBackgroundState extends State<AnimatedGradientBackground>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Alignment?> _beginAnimation;
late Animation<Alignment?> _endAnimation;
final Color color1 = const Color(0xFFfbcfdd);
final Color color2 = const Color(0xFFe2e9fb);
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 10),
)..repeat(reverse: true);
// 创建起始点动画
_beginAnimation = AlignmentTween(
begin: Alignment.topCenter,
end: Alignment.bottomLeft,
).animate(_controller);
// 创建结束点动画
_endAnimation = AlignmentTween(
begin: Alignment.bottomCenter,
end: Alignment.topRight,
).animate(_controller);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [color1, color2],
begin: _beginAnimation.value!,
end: _endAnimation.value!,
),
),
);
},
);
}
}

79
lib/modules/chat/views/chat_view.dart

@ -5,6 +5,7 @@ import 'dart:math';
import '../controllers/chat_controller.dart'; import '../controllers/chat_controller.dart';
import '../models/message_model.dart'; import '../models/message_model.dart';
import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_colors.dart';
import 'animated_gradient_background.dart';
import 'chat_music_card.dart'; import 'chat_music_card.dart';
import 'chat_navigation_card.dart'; import 'chat_navigation_card.dart';
import 'weather_day_card.dart'; import 'weather_day_card.dart';
@ -16,10 +17,17 @@ class ChatView extends GetView<ChatController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark; final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Obx(
backgroundColor: isDarkMode ? AppColors.darkBackground : Colors.grey[50], () => Scaffold(
appBar: _buildAppBar(isDarkMode), backgroundColor:
body: _buildBody(isDarkMode), isDarkMode ? AppColors.darkBackground : Colors.grey[50],
appBar: controller.isVoiceRecognitionActive.value
? null
: _buildAppBar(isDarkMode),
body: controller.isVoiceRecognitionActive.value
? _buildVoiceInputPanel(isDarkMode)
: _buildBody(isDarkMode),
),
); );
} }
@ -47,7 +55,7 @@ class ChatView extends GetView<ChatController> {
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.1), color: Colors.black.withOpacity(0.1),
blurRadius: 3, blurRadius: 3,
offset: Offset(0, 1), offset: const Offset(0, 1),
), ),
], ],
), ),
@ -92,7 +100,7 @@ class ChatView extends GetView<ChatController> {
Container( Container(
width: 6.r, width: 6.r,
height: 6.r, height: 6.r,
decoration: BoxDecoration( decoration: const BoxDecoration(
color: Colors.green, color: Colors.green,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
@ -164,7 +172,7 @@ class ChatView extends GetView<ChatController> {
value: 'clear', value: 'clear',
child: Row( child: Row(
children: [ children: [
Icon(Icons.delete_outline, color: Colors.red), const Icon(Icons.delete_outline, color: Colors.red),
SizedBox(width: 8.w), SizedBox(width: 8.w),
Text( Text(
'clearChatHistory'.tr, // 清空聊天记录 'clearChatHistory'.tr, // 清空聊天记录
@ -205,7 +213,7 @@ class ChatView extends GetView<ChatController> {
), ),
// 底部输入区域 // 底部输入区域
_buildInputArea(isDarkMode), _buildTextInputPanel(isDarkMode),
], ],
); );
} }
@ -377,24 +385,11 @@ class ChatView extends GetView<ChatController> {
return box; return box;
} }
// 构建输入区域 // 构建文本输入面板
Widget _buildInputArea(bool isDarkMode) { Widget _buildTextInputPanel(bool isDarkMode) {
final textController = final textController =
TextEditingController(text: controller.inputText.value); TextEditingController(text: controller.inputText.value);
// 检查是否处于语音识别模式
return Obx(() {
if (controller.isVoiceRecognitionActive.value) {
return _buildVoiceInputPanel(isDarkMode);
} else {
return _buildTextInputPanel(isDarkMode, textController);
}
});
}
// 构建文本输入面板
Widget _buildTextInputPanel(
bool isDarkMode, TextEditingController textController) {
return Container( return Container(
height: 48.w, height: 48.w,
margin: EdgeInsets.only(left: 16.w, right: 16.w, top: 10.w, bottom: 20.w), margin: EdgeInsets.only(left: 16.w, right: 16.w, top: 10.w, bottom: 20.w),
@ -521,16 +516,17 @@ class ChatView extends GetView<ChatController> {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: isDarkMode ? AppColors.cardBackground : Colors.white, color: isDarkMode ? AppColors.cardBackground : Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 3,
offset: Offset(0, -1),
),
],
), ),
child: SafeArea( child: SafeArea(
child: SizedBox( child: Column(
children: [
Row(
children: [],
),
Expanded(
child: AnimatedGradientBackground(),
),
SizedBox(
height: 80.h, height: 80.h,
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w), padding: EdgeInsets.symmetric(horizontal: 20.w),
@ -578,7 +574,8 @@ class ChatView extends GetView<ChatController> {
Container( Container(
height: 50.h, height: 50.h,
child: Obx(() { child: Obx(() {
final isSpeaking = controller.isSpeechDetected.value; final isSpeaking =
controller.isSpeechDetected.value;
return Center( return Center(
child: Container( child: Container(
width: 220.w, width: 220.w,
@ -591,14 +588,17 @@ class ChatView extends GetView<ChatController> {
(index) { (index) {
// 随机高度模拟波形 // 随机高度模拟波形
double height = isSpeaking double height = isSpeaking
? (Random().nextDouble() * 20.0 + 5.0).h ? (Random().nextDouble() * 20.0 +
5.0)
.h
: 2.h; : 2.h;
return SizedBox( return SizedBox(
width: 6.w, width: 6.w,
child: Center( child: Center(
child: AnimatedContainer( child: AnimatedContainer(
duration: Duration(milliseconds: 500), duration: const Duration(
milliseconds: 500),
width: 2.5.w, width: 2.5.w,
height: height, height: height,
margin: EdgeInsets.symmetric( margin: EdgeInsets.symmetric(
@ -622,7 +622,6 @@ class ChatView extends GetView<ChatController> {
); );
}), }),
), ),
SizedBox(height: 8.h),
// 语音状态文本 // 语音状态文本
Obx(() => Text( Obx(() => Text(
@ -662,7 +661,9 @@ class ChatView extends GetView<ChatController> {
child: IconButton( child: IconButton(
icon: Icon( icon: Icon(
Icons.close, Icons.close,
color: isDarkMode ? Colors.white : Colors.grey.shade600, color: isDarkMode
? Colors.white
: Colors.grey.shade600,
size: 28.r, size: 28.r,
), ),
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -674,6 +675,8 @@ class ChatView extends GetView<ChatController> {
), ),
), ),
), ),
],
),
), ),
); );
} }
@ -692,7 +695,7 @@ class ChatView extends GetView<ChatController> {
BoxShadow( BoxShadow(
color: Colors.black.withOpacity(0.05), color: Colors.black.withOpacity(0.05),
blurRadius: 2, blurRadius: 2,
offset: Offset(0, 1), offset: const Offset(0, 1),
), ),
], ],
), ),
@ -730,7 +733,7 @@ class ChatView extends GetView<ChatController> {
// 构建加载动画点 // 构建加载动画点
Widget _buildLoadingDot(int index, bool isDarkMode) { Widget _buildLoadingDot(int index, bool isDarkMode) {
return AnimatedBuilder( return AnimatedBuilder(
animation: AlwaysStoppedAnimation(0), animation: const AlwaysStoppedAnimation(0),
builder: (context, child) { builder: (context, child) {
return Container( return Container(
margin: EdgeInsets.symmetric(horizontal: 2.w), margin: EdgeInsets.symmetric(horizontal: 2.w),

Loading…
Cancel
Save