初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+176
View File
@@ -0,0 +1,176 @@
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<AudioWaveView> createState() => _AudioWaveViewState();
}
class _AudioWaveViewState extends State<AudioWaveView>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late List<Animation<double>> _animations;
@override
void initState() {
super.initState();
_initializeAnimations();
}
/// 初始化动画
void _initializeAnimations() {
_controller = AnimationController(
vsync: this,
duration: widget.duration,
);
_animations = _createWaveAnimations();
_controller.repeat();
}
/// 创建波形动画列表
List<Animation<double>> _createWaveAnimations() {
const int sequenceCount = 15;
final List<Animation<double>> animations = [];
for (int i = 0; i < widget.barCount; i++) {
final source = _generateRandomSequence(sequenceCount);
final tweenSequence = TweenSequence<double>(
List.generate(sequenceCount, (index) {
return TweenSequenceItem<double>(
tween: Tween<double>(
begin: source[index],
end: source[index + 1],
),
weight: 100.0 / sequenceCount,
);
}),
);
animations.add(
tweenSequence.animate(
CurvedAnimation(
parent: _controller,
curve: widget.curve,
),
),
);
}
return animations;
}
/// 生成随机序列
List<double> _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<Widget> _buildWaveBars() {
final List<Widget> 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),
),
),
);
}
}