如何仅使用Flutter实现自定义动画加载进度指示器
Flutter 原生实现自定义动画进度指示器方案
完全基于Flutter自带能力实现,不需要引入任何第三方依赖,核心通过 AnimationController 控制动画时序 + CustomPaint 自定义绘制完成,实现步骤如下:
1. 初始化动画控制器
首先在State类中混入SingleTickerProviderStateMixin,创建动画控制器设置总时长并循环播放,为每个进度节点创建错开延迟的差补动画,形成错落的流动效果:
// 组件定义 class CustomProgressIndicator extends StatefulWidget { final double size; final Color color; final int itemCount; const CustomProgressIndicator({ super.key, this.size = 40, this.color = Colors.blueAccent, this.itemCount = 3 }); @override State<CustomProgressIndicator> createState() => _CustomProgressIndicatorState(); } class _CustomProgressIndicatorState extends State<CustomProgressIndicator> with SingleTickerProviderStateMixin { late AnimationController _controller; late List<Animation<double>> _nodeAnimations; @override void initState() { super.initState(); // 总动画时长1200ms,循环播放 _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 1200) )..repeat(); // 每个节点动画错开20%的间隔,形成差序效果 _nodeAnimations = List.generate(widget.itemCount, (index) { final startInterval = index * 0.2; final endInterval = startInterval + 0.6; return CurvedAnimation( parent: _controller, curve: Interval( startInterval, endInterval < 1.0 ? endInterval : 1.0, curve: Curves.easeInOut ), ); }); } @override void dispose() { _controller.dispose(); super.dispose(); }
2. 自定义绘制动态进度节点
通过CustomPainter将动画值和节点的大小、透明度、位移绑定,直接在画布上绘制每个进度节点,这里示例为圆形弹跳效果,如需适配目标胶囊形进度效果,仅需将绘制方法替换为drawRRect即可:
@override Widget build(BuildContext context) { return SizedBox( width: widget.size, height: widget.size * 0.5, child: AnimatedBuilder( animation: _controller, builder: (context, child) { return CustomPaint( painter: _ProgressPainter( animations: _nodeAnimations, color: widget.color, itemCount: widget.itemCount, ), ); }, ), ); } } class _ProgressPainter extends CustomPainter { final List<Animation<double>> animations; final Color color; final int itemCount; final Paint _paint = Paint(); _ProgressPainter({ required this.animations, required this.color, required this.itemCount }); @override void paint(Canvas canvas, Size size) { final gap = size.width / (itemCount + 1); for (int i = 0; i < itemCount; i++) { final animValue = animations[i].value; // 节点半径随动画值变化 final radius = size.height * 0.2 + animValue * size.height * 0.3; // 节点透明度随动画值变化 final opacity = 0.3 + animValue * 0.7; _paint.color = color.withOpacity(opacity); // 节点位置随动画值上下偏移 final dx = gap * (i + 1); final dy = size.height / 2 - animValue * size.height * 0.2; canvas.drawCircle(Offset(dx, dy), radius, _paint); } } @override bool shouldRepaint(covariant _ProgressPainter oldDelegate) => true; }
3. 使用与效果调整
直接在页面中调用CustomProgressIndicator()即可使用,可通过修改入参调整尺寸、颜色、节点数量,也可以修改动画曲线、间隔时长、绘制逻辑,完全匹配需要的动效样式。
内容的提问来源于stack exchange,提问作者Dean Villamia
相关产品推荐
相关产品推荐

