Flutter中如何实现带无限动画的波浪形进度条?
实现Flutter波浪形进度条的无限循环动画
1. 修改自定义裁剪器,支持动画偏移
原来的静态裁剪器无法实现动态效果,我们给它添加一个偏移参数,用来控制波浪的水平位置,让波浪可以通过平移实现动画:
class MyWaveClipper extends CustomClipper<Path> { final double offset; MyWaveClipper(this.offset); @override Path getClip(Size size) { final path = Path(); final waveSegmentWidth = size.width / 8; final baseY = size.height * 0.2; // 波浪基准高度 final peakY = 0.0; // 波峰高度 final troughY = size.height * 0.4; // 波谷高度 // 构建底部闭合路径 path.lineTo(0, size.height); path.lineTo(size.width, size.height); path.lineTo(size.width, baseY); // 生成波浪路径,多画一段保证偏移后无空白 for (int i = 0; i < 11; i++) { final currentX = size.width - (i * waveSegmentWidth) + offset; final controlY = i % 2 == 0 ? peakY : troughY; path.quadraticBezierTo( currentX - waveSegmentWidth / 2, controlY, currentX - waveSegmentWidth, baseY, ); } path.lineTo(0, baseY); path.close(); return path; } @override bool shouldReclip(covariant MyWaveClipper oldClipper) { return oldClipper.offset != offset; } }
2. 用AnimationController实现无限循环动画
在StatefulWidget中创建动画控制器,驱动偏移量的变化,实现波浪无限平移的效果:
class SquigglySeekbar extends StatefulWidget { @override _SquigglySeekbarState createState() => _SquigglySeekbarState(); } class _SquigglySeekbarState extends State<SquigglySeekbar> with SingleTickerProviderStateMixin { late AnimationController _animationController; late Animation<double> _offsetAnimation; @override void initState() { super.initState(); // 创建动画控制器,设置周期并开启无限循环 _animationController = AnimationController( vsync: this, duration: const Duration(seconds: 2), // 动画速度可自行调整 )..repeat(); // 偏移范围设为单个波浪段宽度,保证波浪衔接无断层 final waveWidth = MediaQuery.of(context).size.width / 8; _offsetAnimation = Tween<double>(begin: 0, end: waveWidth).animate(_animationController); } @override void dispose() { _animationController.dispose(); // 释放动画资源 super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _offsetAnimation, builder: (context, child) { return ClipPath( clipper: MyWaveClipper(_offsetAnimation.value), child: Container( height: 100, // 进度条高度可自定义 color: Colors.blueAccent, // 可添加进度文本、图标等内容 child: const Align( alignment: Alignment.centerLeft, child: Padding( padding: EdgeInsets.only(left: 16), child: Text( "加载中...", style: TextStyle(color: Colors.white, fontSize: 16), ), ), ), ), ); }, ); } }
关键说明
- 偏移驱动动画:通过裁剪器的
offset参数控制波浪水平位置,实现平移效果。 - 无限循环:利用
AnimationController.repeat()让动画持续循环播放。 - 无缝衔接:Tween范围设置为单个波浪段宽度,确保波浪平移后自然衔接,无空白断层。
- 性能优化:
shouldReclip仅在偏移量变化时重绘路径,避免不必要的性能消耗。
内容的提问来源于stack exchange,提问作者Pratik Butani
相关产品推荐
相关产品推荐

