import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../controllers/agent_controller.dart'; /// 声音柱动画组件 (已优化) /// 用于显示语音输入时的音频波形效果 class SoundBarWidget extends StatefulWidget { final double delay; final bool isActive; const SoundBarWidget({ Key? key, required this.delay, required this.isActive, }) : super(key: key); @override State createState() => _SoundBarWidgetState(); } class _SoundBarWidgetState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _animation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 500), ); _animation = Tween(begin: 3, end: 18).animate( CurvedAnimation( parent: _controller, curve: Curves.easeInOut, ), ); // 移除了 .addListener(() { setState(() {}); }) _startOrStopAnimation(); } @override void didUpdateWidget(SoundBarWidget oldWidget) { super.didUpdateWidget(oldWidget); if (widget.isActive != oldWidget.isActive) { _startOrStopAnimation(); } } /// 开始或停止动画 void _startOrStopAnimation() { // 确保组件仍然挂载在树上 if (!mounted) return; if (widget.isActive) { Future.delayed(Duration(milliseconds: (widget.delay * 1000).toInt()), () { if (mounted && widget.isActive) { _controller.repeat(reverse: true); } }); } else { // 停止并平滑地过渡到初始状态 _controller.stop(); _controller.animateTo(0.0, duration: const Duration(milliseconds: 200), curve: Curves.easeOut); } } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final primaryColor = Theme.of(context).primaryColor; // 使用 AnimatedBuilder 来优化性能 return AnimatedBuilder( animation: _animation, builder: (context, child) { return Container( width: 2.5, // 当动画不活跃时,高度固定为3;活跃时使用动画值 height: widget.isActive ? _animation.value : 3, margin: const EdgeInsets.symmetric(horizontal: 1), decoration: BoxDecoration( color: widget.isActive ? primaryColor.withOpacity(0.8) : Colors.grey.withOpacity(0.4), borderRadius: BorderRadius.circular(1.5), ), ); }, ); } } /// 声音柱组合组件 (无需改动) /// 包含多个声音柱的组合显示 class SoundBarsWidget extends StatelessWidget { final bool isActive; final int barCount; const SoundBarsWidget({ Key? key, required this.isActive, this.barCount = 10, }) : super(key: key); @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(barCount, (index) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 1), child: SoundBarWidget( delay: index * 0.1, isActive: isActive, ), ); }), ); } } /// 带控制器集成的声音柱组件 (无需改动) /// 自动从AgentController获取状态 class AgentSoundBarsWidget extends StatelessWidget { final int barCount; const AgentSoundBarsWidget({ Key? key, this.barCount = 10, }) : super(key: key); @override Widget build(BuildContext context) { return Obx(() { final controller = Get.find(); final shouldShowAnimation = controller.isListening.value || controller.isPushToTalkActive.value; return SoundBarsWidget( isActive: shouldShowAnimation, barCount: barCount, ); }); } }