说明
实现一个渐变圆环,起点位置为- π / 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;
// 💡关键:首尾颜色一致,更改stops
const 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),
),
],
),
)