You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 23:06:02