2025-08-12 16:47:34 +08:00
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
import 'dart:math' as math;
|
|
|
|
|
|
|
|
|
|
|
|
/// 小型按钮波形动画组件
|
|
|
|
|
|
///
|
2025-08-12 17:40:39 +08:00
|
|
|
|
/// 用于显示适合小按钮的波形动画,竖线数量根据容器宽度自动计算
|
2025-08-12 16:47:34 +08:00
|
|
|
|
class AudioWaveLargeMini extends StatelessWidget {
|
|
|
|
|
|
/// 动画控制器,用于驱动波形动画
|
|
|
|
|
|
final AnimationController animationController;
|
|
|
|
|
|
|
|
|
|
|
|
/// 波形颜色,默认为白色
|
|
|
|
|
|
final Color waveColor;
|
|
|
|
|
|
|
2025-08-12 17:40:39 +08:00
|
|
|
|
/// 波形条间距,默认为3.0px
|
|
|
|
|
|
final double barSpacing;
|
|
|
|
|
|
|
|
|
|
|
|
/// 最小高度比例,默认为0.3(相对于容器高度)
|
|
|
|
|
|
final double minHeightRatio;
|
|
|
|
|
|
|
|
|
|
|
|
/// 最大高度比例,默认为1.0(相对于容器高度)
|
|
|
|
|
|
final double maxHeightRatio;
|
|
|
|
|
|
|
2025-08-12 16:47:34 +08:00
|
|
|
|
/// 构造函数
|
|
|
|
|
|
const AudioWaveLargeMini({
|
|
|
|
|
|
super.key,
|
|
|
|
|
|
required this.animationController,
|
|
|
|
|
|
this.waveColor = Colors.white,
|
2025-08-12 17:40:39 +08:00
|
|
|
|
this.barSpacing = 3.0,
|
|
|
|
|
|
this.minHeightRatio = 0.3,
|
|
|
|
|
|
this.maxHeightRatio = 1.0,
|
2025-08-12 16:47:34 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
|
return AnimatedBuilder(
|
|
|
|
|
|
animation: animationController, // 使用传入的动画控制器
|
|
|
|
|
|
builder: (context, child) {
|
2025-08-12 17:40:39 +08:00
|
|
|
|
return LayoutBuilder(
|
|
|
|
|
|
builder: (context, constraints) {
|
|
|
|
|
|
// 根据容器宽度动态计算竖线数量
|
|
|
|
|
|
final containerWidth = constraints.maxWidth;
|
|
|
|
|
|
final containerHeight = constraints.maxHeight;
|
|
|
|
|
|
final barWidthWithSpacing = 2 + barSpacing;
|
|
|
|
|
|
final barCount = (containerWidth / barWidthWithSpacing).floor().clamp(3, 15);
|
2025-08-12 16:47:34 +08:00
|
|
|
|
|
2025-08-12 17:40:39 +08:00
|
|
|
|
return Row(
|
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center, // 改为垂直居中,和AudioWaveLarge一致
|
|
|
|
|
|
children: List.generate(barCount, (index) {
|
|
|
|
|
|
// 为每个竖线设置不同的相位,和AudioWaveLarge保持一致
|
|
|
|
|
|
final phase = index * 0.3; // 改为0.3,和AudioWaveLarge一致
|
|
|
|
|
|
// 设置不同的频率变化
|
|
|
|
|
|
final frequency = 1.0 + (index % 3) * 0.2;
|
|
|
|
|
|
|
|
|
|
|
|
// 根据容器高度计算波形高度,使用和AudioWaveLarge相同的算法
|
|
|
|
|
|
final minHeight = containerHeight * minHeightRatio;
|
|
|
|
|
|
final maxHeight = containerHeight * maxHeightRatio;
|
|
|
|
|
|
final height = minHeight + (maxHeight - minHeight) * math.sin(
|
|
|
|
|
|
(animationController.value * 2 * math.pi * frequency) + phase
|
|
|
|
|
|
).abs();
|
|
|
|
|
|
|
|
|
|
|
|
// 构建单个波形条
|
|
|
|
|
|
return Padding(
|
|
|
|
|
|
padding: EdgeInsets.symmetric(horizontal: barSpacing / 2),
|
|
|
|
|
|
child: Container(
|
|
|
|
|
|
width: 2, // 波形条宽度2px
|
|
|
|
|
|
height: height, // 高度随动画变化
|
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
|
|
color: waveColor,
|
|
|
|
|
|
borderRadius: BorderRadius.circular(1), // 圆角效果
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
}),
|
2025-08-12 16:47:34 +08:00
|
|
|
|
);
|
2025-08-12 17:40:39 +08:00
|
|
|
|
},
|
2025-08-12 16:47:34 +08:00
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|