103 lines
2.6 KiB
Dart
103 lines
2.6 KiB
Dart
import 'dart:math';
|
|
import 'package:flutter/material.dart';
|
|
|
|
class ProgressRing extends StatelessWidget {
|
|
final double progress; // 0.0 to 1.0
|
|
final double size;
|
|
final double strokeWidth;
|
|
final Color backgroundColor;
|
|
final Color progressColor;
|
|
final Widget? child;
|
|
|
|
const ProgressRing({
|
|
super.key,
|
|
required this.progress,
|
|
this.size = 120,
|
|
this.strokeWidth = 12,
|
|
this.backgroundColor = Colors.grey,
|
|
this.progressColor = Colors.blue,
|
|
this.child,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SizedBox(
|
|
width: size,
|
|
height: size,
|
|
child: CustomPaint(
|
|
painter: _ProgressRingPainter(
|
|
progress: progress,
|
|
strokeWidth: strokeWidth,
|
|
backgroundColor: backgroundColor,
|
|
progressColor: progressColor,
|
|
),
|
|
child: child != null
|
|
? Center(child: child)
|
|
: Center(
|
|
child: Text(
|
|
'${(progress * 100).toStringAsFixed(0)}%',
|
|
style: TextStyle(
|
|
fontSize: size / 5,
|
|
fontWeight: FontWeight.bold,
|
|
color: Colors.grey.shade800,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ProgressRingPainter extends CustomPainter {
|
|
final double progress;
|
|
final double strokeWidth;
|
|
final Color backgroundColor;
|
|
final Color progressColor;
|
|
|
|
_ProgressRingPainter({
|
|
required this.progress,
|
|
required this.strokeWidth,
|
|
required this.backgroundColor,
|
|
required this.progressColor,
|
|
});
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final center = Offset(size.width / 2, size.height / 2);
|
|
final radius = (size.width - strokeWidth) / 2;
|
|
|
|
// Background circle
|
|
final backgroundPaint = Paint()
|
|
..color = backgroundColor.withAlpha(120)
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = strokeWidth
|
|
..strokeCap = StrokeCap.round;
|
|
|
|
canvas.drawCircle(center, radius, backgroundPaint);
|
|
|
|
// Progress arc
|
|
final progressPaint = Paint()
|
|
..shader = LinearGradient(
|
|
colors: [
|
|
progressColor,
|
|
progressColor.withAlpha(170),
|
|
],
|
|
).createShader(Rect.fromCircle(center: center, radius: radius))
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = strokeWidth
|
|
..strokeCap = StrokeCap.round;
|
|
|
|
final sweepAngle = 2 * pi * progress;
|
|
canvas.drawArc(
|
|
Rect.fromCircle(center: center, radius: radius),
|
|
-pi / 2, // Start from top
|
|
sweepAngle,
|
|
false,
|
|
progressPaint,
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
|
|
}
|