说明
实现一个渐变圆环,起点位置为- π / 2
。
效果
源码
- GradientCircularPainter1
class GradientCircularPainter1 extends CustomPainter {final double progress;GradientCircularPainter1(this.progress);void paint(Canvas canvas, Size size) {const double strokeWidth = 8;final center = size.center(Offset.zero);final radius = (size.width - 2 * strokeWidth) / 2;// 整个圆环的背景色:绘制灰色圆环填充剩余部分final bgPaint = Paint()..color = Colors.grey.withOpacity(0.2)..style = PaintingStyle.stroke..strokeWidth = strokeWidth;canvas.drawArc(Rect.fromCircle(center: center, radius: radius),0.0,2 * pi,false,bgPaint,);// 渐变进度条final rect = Offset.zero & size;const gradient =SweepGradient(colors: [Color(0xff40A9FD), Color(0xFF7451FF)]);final paint = Paint()..shader = gradient.createShader(rect)..style = PaintingStyle.stroke..strokeWidth = strokeWidth;const startAngle = -pi / 2;final sweepAngle = (2 * pi) * progress;canvas.drawArc(Rect.fromCircle(center: center, radius: radius),startAngle,sweepAngle,false,paint,);} bool shouldRepaint(GradientCircularPainter1 oldDelegate) {return progress != oldDelegate.progress;}
}
- GradientCircularPainter2
class GradientCircularPainter2 extends CustomPainter {final double progress;GradientCircularPainter2(this.progress);void paint(Canvas canvas, Size size) {const double strokeWidth = 8;final center = size.center(Offset.zero);final radius = (size.width - 2 * strokeWidth) / 2;// 整个圆环的背景色:绘制灰色圆环填充剩余部分final bgPaint = Paint()..color = Colors.grey.withOpacity(0.2)..style = PaintingStyle.stroke..strokeWidth = strokeWidth;canvas.drawArc(Rect.fromCircle(center: center, radius: radius),0.0,2 * pi,false,bgPaint,);// 渐变进度条final rect = Offset.zero & size;const gradient =SweepGradient(colors: [Color(0xff40A9FD), Color(0xFF7451FF)]);final paint = Paint()..shader = gradient.createShader(rect)..style = PaintingStyle.stroke..strokeWidth = strokeWidth;// 💡关键:画布逆时针旋转90度canvas.save();canvas.translate(center.dx, center.dy);canvas.rotate(-pi / 2);canvas.translate(-center.dx, -center.dy);const startAngle = 0.0;final sweepAngle = (2 * pi) * progress;canvas.drawArc(Rect.fromCircle(center: center, radius: radius),startAngle,sweepAngle,false,paint,);canvas.restore();} bool shouldRepaint(GradientCircularPainter2 oldDelegate) =>progress != oldDelegate.progress;
}
- GradientCircularPainter3
class GradientCircularPainter3 extends CustomPainter {final double progress;GradientCircularPainter3(this.progress);void paint(Canvas canvas, Size size) {const double strokeWidth = 8;final center = size.center(Offset.zero);final radius = (size.width - 2 * strokeWidth) / 2;// 整个圆环的背景色:绘制灰色圆环填充剩余部分final bgPaint = Paint()..color = Colors.grey.withOpacity(0.2)..style = PaintingStyle.stroke..strokeWidth = strokeWidth;canvas.drawArc(Rect.fromCircle(center: center, radius: radius),0.0,2 * pi,false,bgPaint,);// 渐变进度条final rect = Offset.zero & size;// 💡关键:首尾颜色一致,更改stopsconst gradient = SweepGradient(colors: [Color(0xff40A9FD), Color(0xFF7451FF), Color(0xff40A9FD)],stops: [0.0, 0.5, 0.7],tileMode: TileMode.clamp);final paint = Paint()..shader = gradient.createShader(rect)..style = PaintingStyle.stroke..strokeWidth = strokeWidth;const startAngle = -pi / 2;final sweepAngle = (2 * pi) * progress;canvas.drawArc(Rect.fromCircle(center: center, radius: radius),startAngle,sweepAngle,false,paint,);} bool shouldRepaint(GradientCircularPainter3 oldDelegate) {return progress != oldDelegate.progress;}
}
- UI渲染
Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [const SizedBox(height: 20,),// 不是想要的渐变效果CustomPaint(size: const Size(60, 60),painter: GradientCircularPainter1(0.8),),const SizedBox(height: 20,),// 可取CustomPaint(size: const Size(60, 60),painter: GradientCircularPainter2(0.8),),const SizedBox(height: 20,),// 可取CustomPaint(size: const Size(60, 60),painter: GradientCircularPainter3(0.8),),],),)