Browse Source
将声音柱动画逻辑提取为独立组件SoundBarWidget,并添加组合组件SoundBarsWidget和集成控制器的AgentSoundBarsWidget 移除agent_view中原有的_SoundBar实现,使用新组件替代newdev_shunjiawei
2 changed files with 146 additions and 97 deletions
@ -0,0 +1,143 @@ |
|||||
|
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<SoundBarWidget> createState() => _SoundBarWidgetState(); |
||||
|
} |
||||
|
|
||||
|
class _SoundBarWidgetState extends State<SoundBarWidget> |
||||
|
with SingleTickerProviderStateMixin { |
||||
|
late AnimationController _controller; |
||||
|
late Animation<double> _animation; |
||||
|
|
||||
|
@override |
||||
|
void initState() { |
||||
|
super.initState(); |
||||
|
|
||||
|
_controller = AnimationController( |
||||
|
vsync: this, |
||||
|
duration: const Duration(milliseconds: 500), |
||||
|
); |
||||
|
|
||||
|
_animation = Tween<double>(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 (widget.isActive) { |
||||
|
Future.delayed(Duration(milliseconds: (widget.delay * 1000).toInt()), () { |
||||
|
if (mounted && widget.isActive) { |
||||
|
_controller.repeat(reverse: true); |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
_controller.reset(); |
||||
|
// 设置为小高度的静态状态 |
||||
|
_controller.animateTo(0.1, duration: const Duration(milliseconds: 300)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
void dispose() { |
||||
|
_controller.dispose(); |
||||
|
super.dispose(); |
||||
|
} |
||||
|
|
||||
|
@override |
||||
|
Widget build(BuildContext context) { |
||||
|
final primaryColor = Theme.of(context).primaryColor; |
||||
|
|
||||
|
return Container( |
||||
|
width: 2.5, |
||||
|
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.start, |
||||
|
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<AgentController>(); |
||||
|
return SoundBarsWidget( |
||||
|
isActive: controller.isListening.value, |
||||
|
barCount: barCount, |
||||
|
); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue