filament_verwaltung/lib/widgets/progress_ring.dart
2026-01-15 11:40:09 +01:00

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;
}