You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
3.5 KiB
143 lines
3.5 KiB
2 years ago
|
import 'dart:math' as math;
|
||
|
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter/scheduler.dart';
|
||
|
|
||
|
const halfPi = pi / 2;
|
||
|
const pi = math.pi;
|
||
|
|
||
|
typedef LabelBuilder = Widget Function(double value);
|
||
|
|
||
|
class RingIndicator extends StatefulWidget {
|
||
|
const RingIndicator({
|
||
|
Key? key,
|
||
|
this.backgroundColor = Colors.grey,
|
||
|
this.ringWidth = 10,
|
||
|
this.startAngel = 0,
|
||
|
this.endAngel = pi * 2,
|
||
|
required this.ringColor,
|
||
|
required this.maxValue,
|
||
|
this.minValue = 0,
|
||
|
required this.value,
|
||
|
this.innerRing,
|
||
|
this.labelBuilder,
|
||
|
}) : super(key: key);
|
||
|
|
||
|
final Color backgroundColor;
|
||
|
final double ringWidth;
|
||
|
final Color ringColor;
|
||
|
final double startAngel;
|
||
|
final double endAngel;
|
||
|
final double maxValue;
|
||
|
final double minValue;
|
||
|
final double value;
|
||
|
final RingIndicator? innerRing;
|
||
|
final LabelBuilder? labelBuilder;
|
||
|
|
||
|
@override
|
||
|
State<RingIndicator> createState() => _RingIndicatorState();
|
||
|
}
|
||
|
|
||
|
class _RingIndicatorState extends State<RingIndicator> {
|
||
|
double? _value = 0;
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
var value = _value ?? widget.value;
|
||
|
var fillAngel =
|
||
|
((value - widget.minValue) / (widget.maxValue - widget.minValue)) * (widget.endAngel - widget.startAngel);
|
||
|
return Center(
|
||
|
child: SizedBox.expand(
|
||
|
child: CustomPaint(
|
||
|
painter: _RingIndicatorPainter(
|
||
|
backgroundColor: widget.backgroundColor,
|
||
|
ringWidth: widget.ringWidth,
|
||
|
startAngel: widget.startAngel,
|
||
|
endAngel: widget.endAngel,
|
||
|
ringColor: widget.ringColor,
|
||
|
fillAngel: fillAngel,
|
||
|
),
|
||
|
child: Stack(
|
||
|
children: [
|
||
|
if (widget.labelBuilder != null) widget.labelBuilder!(value),
|
||
|
],
|
||
|
),
|
||
|
),
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
Ticker? ticker;
|
||
|
|
||
|
@override
|
||
|
void didUpdateWidget(RingIndicator oldWidget) {
|
||
|
super.didUpdateWidget(oldWidget);
|
||
|
var startTime = DateTime.now();
|
||
|
ticker?.stop();
|
||
|
ticker = Ticker((_) {
|
||
|
var diff = DateTime.now().difference(startTime).inMilliseconds;
|
||
|
if (diff > 300) {
|
||
|
return ticker?.stop();
|
||
|
}
|
||
|
if (mounted) {
|
||
|
setState(() {
|
||
|
_value = oldWidget.value + (widget.value - oldWidget.value) * (diff / 300);
|
||
|
});
|
||
|
}
|
||
|
})
|
||
|
..start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class _RingIndicatorPainter extends CustomPainter {
|
||
|
_RingIndicatorPainter({
|
||
|
required this.backgroundColor,
|
||
|
required this.ringWidth,
|
||
|
required this.ringColor,
|
||
|
required this.startAngel,
|
||
|
required this.fillAngel,
|
||
|
required this.endAngel,
|
||
|
}) : _paint = Paint()
|
||
|
..strokeWidth = ringWidth
|
||
|
..style = PaintingStyle.stroke
|
||
|
..strokeCap = StrokeCap.round;
|
||
|
|
||
|
final Color backgroundColor;
|
||
|
final double ringWidth;
|
||
|
final Color ringColor;
|
||
|
final double startAngel;
|
||
|
final double fillAngel;
|
||
|
final double endAngel;
|
||
|
|
||
|
final Paint _paint;
|
||
|
|
||
|
@override
|
||
|
void paint(Canvas canvas, Size size) {
|
||
|
canvas.drawArc(
|
||
|
Rect.fromCenter(
|
||
|
center: size.center(Offset.zero),
|
||
|
width: size.width,
|
||
|
height: size.height,
|
||
|
),
|
||
|
startAngel - halfPi,
|
||
|
endAngel - startAngel,
|
||
|
false,
|
||
|
_paint..color = backgroundColor,
|
||
|
);
|
||
|
canvas.drawArc(
|
||
|
Rect.fromCenter(
|
||
|
center: size.center(Offset.zero),
|
||
|
width: size.width,
|
||
|
height: size.height,
|
||
|
),
|
||
|
startAngel - halfPi,
|
||
|
fillAngel,
|
||
|
false,
|
||
|
_paint..color = ringColor,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
bool shouldRepaint(covariant _RingIndicatorPainter oldDelegate) => true;
|
||
|
}
|