87 lines
2.0 KiB
Dart
87 lines
2.0 KiB
Dart
import 'dart:math' as math;
|
|
import 'package:flutter/material.dart';
|
|
import '../theme.dart';
|
|
|
|
class ProgressRing extends StatelessWidget {
|
|
final double percent;
|
|
final double size;
|
|
final double strokeWidth;
|
|
final Color? color;
|
|
final Color? backgroundColor;
|
|
|
|
const ProgressRing({
|
|
super.key,
|
|
required this.percent,
|
|
this.size = 36,
|
|
this.strokeWidth = 3,
|
|
this.color,
|
|
this.backgroundColor,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final effectiveColor = percent >= 95
|
|
? MirrorTheme.success
|
|
: (color ?? MirrorTheme.accent);
|
|
|
|
return SizedBox(
|
|
width: size,
|
|
height: size,
|
|
child: CustomPaint(
|
|
painter: _ProgressRingPainter(
|
|
percent: percent.clamp(0, 100),
|
|
strokeWidth: strokeWidth,
|
|
color: effectiveColor,
|
|
backgroundColor: backgroundColor ?? MirrorTheme.surfaceLight,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ProgressRingPainter extends CustomPainter {
|
|
final double percent;
|
|
final double strokeWidth;
|
|
final Color color;
|
|
final Color backgroundColor;
|
|
|
|
_ProgressRingPainter({
|
|
required this.percent,
|
|
required this.strokeWidth,
|
|
required this.color,
|
|
required this.backgroundColor,
|
|
});
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final center = Offset(size.width / 2, size.height / 2);
|
|
final radius = (size.width - strokeWidth) / 2;
|
|
|
|
final bgPaint = Paint()
|
|
..color = backgroundColor
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = strokeWidth;
|
|
|
|
final fgPaint = Paint()
|
|
..color = color
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = strokeWidth
|
|
..strokeCap = StrokeCap.round;
|
|
|
|
canvas.drawCircle(center, radius, bgPaint);
|
|
|
|
final sweepAngle = (percent / 100) * 2 * math.pi;
|
|
canvas.drawArc(
|
|
Rect.fromCircle(center: center, radius: radius),
|
|
-math.pi / 2,
|
|
sweepAngle,
|
|
false,
|
|
fgPaint,
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(_ProgressRingPainter oldDelegate) =>
|
|
oldDelegate.percent != percent || oldDelegate.color != color;
|
|
}
|