import 'dart:math'; import 'package:flutter/material.dart'; /// 音频波形动画组件 /// 用于显示音频播放时的动态波形效果 class AudioWaveView extends StatefulWidget { /// 波形高度 final double height; /// 波形颜色 final Color color; /// 动画持续时间 final Duration duration; /// 动画曲线 final Curve curve; /// 波形条之间的间距 final double margin; /// 波形条的宽度 final double width; /// 波形条的数量 final int barCount; const AudioWaveView({ super.key, this.height = 12, this.margin = 3, this.width = 1.5, this.color = const Color(0xffF68804), this.duration = const Duration(seconds: 5), this.curve = Curves.easeInOut, this.barCount = 3, }); @override State createState() => _AudioWaveViewState(); } class _AudioWaveViewState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late List> _animations; @override void initState() { super.initState(); _initializeAnimations(); } /// 初始化动画 void _initializeAnimations() { _controller = AnimationController( vsync: this, duration: widget.duration, ); _animations = _createWaveAnimations(); _controller.repeat(); } /// 创建波形动画列表 List> _createWaveAnimations() { const int sequenceCount = 15; final List> animations = []; for (int i = 0; i < widget.barCount; i++) { final source = _generateRandomSequence(sequenceCount); final tweenSequence = TweenSequence( List.generate(sequenceCount, (index) { return TweenSequenceItem( tween: Tween( begin: source[index], end: source[index + 1], ), weight: 100.0 / sequenceCount, ); }), ); animations.add( tweenSequence.animate( CurvedAnimation( parent: _controller, curve: widget.curve, ), ), ); } return animations; } /// 生成随机序列 List _generateRandomSequence(int count) { final random = Random(); final source = List.generate(count, (_) => random.nextDouble()); source.add(source.first); // 确保循环 return source; } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, builder: (context, child) { return Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisSize: MainAxisSize.min, children: _buildWaveBars(), ); }, ); } /// 构建波形条列表 List _buildWaveBars() { final List bars = []; for (int i = 0; i < widget.barCount; i++) { if (i > 0) { bars.add(SizedBox(width: widget.margin)); } bars.add( WaveBar( color: widget.color, width: widget.width, height: _animations[i].value * widget.height, ), ); } return bars; } } /// 单个波形条组件 class WaveBar extends StatelessWidget { final double width; final double height; final Color color; const WaveBar({ super.key, required this.width, required this.height, required this.color, }); @override Widget build(BuildContext context) { return SizedBox( width: width, height: height, child: DecoratedBox( decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(width / 2), ), ), ); } }