如何在Flutter中实现与示例图一致的自定义圆形进度指示器
Flutter 自定义圆形旋转进度指示器实现方案

我希望在Flutter中实现与示例图完全一致的自定义圆形进度指示器,尝试多种方法仍未成功。我刚接触动画开发,恳请提供帮助或指导。
修正后的完整代码
import 'package:flutter/material.dart'; import 'dart:math'; void main() { runApp(const MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( backgroundColor: Colors.white, body: Center(child: RotatingCircularProgress()), ), )); } class RotatingCircularProgress extends StatefulWidget { const RotatingCircularProgress({super.key}); @override State<RotatingCircularProgress> createState() => _RotatingCircularProgressState(); } class _RotatingCircularProgressState extends State<RotatingCircularProgress> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _rotationAnimation; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(seconds: 2), )..repeat(); // 无限循环动画 // 生成0到2π的旋转动画值 _rotationAnimation = Tween<double>(begin: 0, end: 2 * pi).animate(_controller); } @override Widget build(BuildContext context) { return SizedBox( width: 100, height: 100, child: AnimatedBuilder( animation: _rotationAnimation, builder: (context, child) { return CustomPaint( painter: CircularProgressPainter(rotationAngle: _rotationAnimation.value), ); }, ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } } class CircularProgressPainter extends CustomPainter { final double rotationAngle; CircularProgressPainter({required this.rotationAngle}); @override void paint(Canvas canvas, Size size) { final center = size.center(Offset.zero); final radius = size.width / 2 - 5; // 减去一半描边宽度,避免超出容器 final strokeWidth = 10.0; const startAngle = -pi / 2; // 从顶部开始绘制圆弧 const sweepAngle = 1.7 * pi; // 绘制约3/4圆的弧长 // 创建渐变,通过旋转矩阵让渐变跟随动画角度变化 final gradient = SweepGradient( colors: [ Colors.green, // 起始绿色 Colors.green.withOpacity(0.7), Colors.green.withOpacity(0.4), Colors.green.withOpacity(0.1), Colors.white, // 末端白色 ], stops: const [0.0, 0.3, 0.6, 0.85, 1.0], tileMode: TileMode.clamp, transform: GradientRotation(rotationAngle), // 关联动画旋转角度 ); final paint = Paint() ..shader = gradient.createShader(Rect.fromCircle(center: center, radius: radius)) ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..strokeCap = StrokeCap.round; // 圆弧起始端为圆角 // 绘制固定位置的圆弧,渐变随动画旋转 canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, sweepAngle, false, paint, ); } @override bool shouldRepaint(covariant CircularProgressPainter oldDelegate) { return oldDelegate.rotationAngle != rotationAngle; } }
关键修改说明
- 动画作用对象调整:不再旋转整个圆弧组件,而是将动画值关联到渐变的
GradientRotation变换,让渐变方向随动画旋转,实现示例图中“透明尾部绕圈”的效果 - 圆弧位置优化:调整
radius减去一半描边宽度,避免圆弧超出容器范围;将起始角度设为-pi/2(顶部),更符合常见的圆形指示器起始位置 - 重绘逻辑修正:
shouldRepaint方法对比旋转角度值,只有当动画值变化时才触发重绘,提升性能 - 渐变关联动画:通过
GradientRotation将动画角度传递给渐变,让渐变的过渡区域随动画旋转,完美匹配示例图的动态效果
内容的提问来源于stack exchange,提问作者prabin maharjan
相关产品推荐
相关产品推荐

