implement inner ring.
This commit is contained in:
+82
-20
@@ -16,15 +16,9 @@ class MyApp extends StatelessWidget {
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
home: const FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
child: SizedBox(
|
||||
width: 720,
|
||||
height: 1080,
|
||||
child: MyHomePage(title: 'Flutter Demo Home Page'),
|
||||
),
|
||||
),
|
||||
home: const MyHomePage(title: 'Flutter Demo Home Page'),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -39,11 +33,15 @@ class MyHomePage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
double value = 0;
|
||||
double value1 = 30;
|
||||
double value2 = 50;
|
||||
double value3 = 10;
|
||||
|
||||
void _incrementCounter() {
|
||||
setState(() {
|
||||
value = Random().nextDouble() * 100;
|
||||
value1 = Random().nextDouble() * 100;
|
||||
value2 = Random().nextDouble() * 100;
|
||||
value3 = Random().nextDouble() * 100;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,23 +56,87 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
SizedBox.square(
|
||||
dimension: 100,
|
||||
dimension: 200,
|
||||
child: RingIndicator(
|
||||
ringColor: Colors.deepPurpleAccent,
|
||||
startAngel: pi * -0.7,
|
||||
endAngel: pi * 0.7,
|
||||
maxValue: 100,
|
||||
value: value,
|
||||
labelBuilder: (value) => Center(
|
||||
child: Text(
|
||||
value.toStringAsFixed(1),
|
||||
style: const TextStyle(color: Colors.teal, fontSize: 24),
|
||||
)),
|
||||
value: value1,
|
||||
labelBuilder: (values) {
|
||||
return [
|
||||
const Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Text(
|
||||
'CPU',
|
||||
style: TextStyle(fontSize: 38),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(values.level(0)?.toStringAsFixed(1) ?? '/', style: const TextStyle(fontSize: 18)),
|
||||
Text(values.level(1)?.toStringAsFixed(1) ?? '/', style: const TextStyle(fontSize: 24)),
|
||||
Text(values.level(2)?.toStringAsFixed(1) ?? '/', style: const TextStyle(fontSize: 18)),
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
innerRing: RingIndicator(
|
||||
startAngel: pi * -0.7,
|
||||
endAngel: pi * 0.7,
|
||||
maxValue: 100,
|
||||
ringColor: Colors.teal,
|
||||
value: value2,
|
||||
innerRing: RingIndicator(
|
||||
startAngel: pi * -0.7,
|
||||
endAngel: pi * 0.7,
|
||||
ringColor: Colors.amber,
|
||||
maxValue: 100,
|
||||
value: value3,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'$value',
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
const SizedBox(height: 50),
|
||||
SizedBox.square(
|
||||
dimension: 200,
|
||||
child: RingIndicator(
|
||||
ringColor: Colors.teal,
|
||||
startAngel: halfPi,
|
||||
maxValue: 100,
|
||||
value: value1,
|
||||
labelBuilder: (values) => [
|
||||
const Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Text('RAM', style: TextStyle(fontSize: 38, height: 1.8)),
|
||||
),
|
||||
Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(values.level(2)?.toStringAsFixed(1) ?? '/', style: const TextStyle(fontSize: 18)),
|
||||
Text(values.level(1)?.toStringAsFixed(1) ?? '/', style: const TextStyle(fontSize: 24)),
|
||||
Text(values.level(0)?.toStringAsFixed(1) ?? '/', style: const TextStyle(fontSize: 18)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
innerRing: RingIndicator(
|
||||
ringColor: Colors.deepOrange,
|
||||
startAngel: halfPi,
|
||||
maxValue: 100,
|
||||
value: value2,
|
||||
innerRing: RingIndicator(
|
||||
ringColor: Colors.indigoAccent,
|
||||
startAngel: halfPi,
|
||||
maxValue: 100,
|
||||
value: value3,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
+71
-11
@@ -6,12 +6,33 @@ import 'package:flutter/scheduler.dart';
|
||||
const halfPi = pi / 2;
|
||||
const pi = math.pi;
|
||||
|
||||
typedef LabelBuilder = Widget Function(double value);
|
||||
typedef LabelBuilder = Iterable<Widget> Function(List<LevelValue> values);
|
||||
|
||||
extension LevelValueExt on List<LevelValue> {
|
||||
double? level(int level) {
|
||||
for (var element in this) {
|
||||
if (element.level == level) return element.value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class LevelValue {
|
||||
final double value;
|
||||
final int level;
|
||||
|
||||
const LevelValue(this.value) : level = 0;
|
||||
|
||||
const LevelValue._withLevel(this.value, this.level);
|
||||
|
||||
LevelValue incrementLevel() => LevelValue._withLevel(value, level + 1);
|
||||
}
|
||||
|
||||
class RingIndicator extends StatefulWidget {
|
||||
const RingIndicator({
|
||||
Key? key,
|
||||
this.backgroundColor = Colors.grey,
|
||||
this.backgroundColor = Colors.white12,
|
||||
this.ringWidth = 10,
|
||||
this.startAngel = 0,
|
||||
this.endAngel = pi * 2,
|
||||
@@ -21,7 +42,9 @@ class RingIndicator extends StatefulWidget {
|
||||
required this.value,
|
||||
this.innerRing,
|
||||
this.labelBuilder,
|
||||
}) : super(key: key);
|
||||
double? gap,
|
||||
}) : gap = gap ?? ringWidth / 2,
|
||||
super(key: key);
|
||||
|
||||
final Color backgroundColor;
|
||||
final double ringWidth;
|
||||
@@ -33,19 +56,22 @@ class RingIndicator extends StatefulWidget {
|
||||
final double value;
|
||||
final RingIndicator? innerRing;
|
||||
final LabelBuilder? labelBuilder;
|
||||
final double gap;
|
||||
|
||||
@override
|
||||
State<RingIndicator> createState() => _RingIndicatorState();
|
||||
}
|
||||
|
||||
class _RingIndicatorState extends State<RingIndicator> {
|
||||
double? _value = 0;
|
||||
double _value = 0;
|
||||
Map<int, LevelValue> values = {};
|
||||
|
||||
_RingIndicatorState? parent;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var value = _value ?? widget.value;
|
||||
var fillAngel =
|
||||
((value - widget.minValue) / (widget.maxValue - widget.minValue)) * (widget.endAngel - widget.startAngel);
|
||||
((_value - widget.minValue) / (widget.maxValue - widget.minValue)) * (widget.endAngel - widget.startAngel);
|
||||
return Center(
|
||||
child: SizedBox.expand(
|
||||
child: CustomPaint(
|
||||
@@ -59,7 +85,12 @@ class _RingIndicatorState extends State<RingIndicator> {
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
if (widget.labelBuilder != null) widget.labelBuilder!(value),
|
||||
if (widget.innerRing != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.all(widget.ringWidth + widget.gap),
|
||||
child: widget.innerRing,
|
||||
),
|
||||
if (widget.labelBuilder != null) ...widget.labelBuilder!(values.values.toList()),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -69,9 +100,7 @@ class _RingIndicatorState extends State<RingIndicator> {
|
||||
|
||||
Ticker? ticker;
|
||||
|
||||
@override
|
||||
void didUpdateWidget(RingIndicator oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
_handleValueChange(double newValue, double oldValue) {
|
||||
var startTime = DateTime.now();
|
||||
ticker?.stop();
|
||||
ticker = Ticker((_) {
|
||||
@@ -81,12 +110,43 @@ class _RingIndicatorState extends State<RingIndicator> {
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_value = oldWidget.value + (widget.value - oldWidget.value) * (diff / 300);
|
||||
_value = oldValue + (newValue - oldValue) * (diff / 300);
|
||||
values[0] = LevelValue(_value);
|
||||
});
|
||||
if (parent != null) {
|
||||
for (var value in values.values) {
|
||||
parent!.updateValue(value.incrementLevel());
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
..start();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_handleValueChange(widget.value, 0);
|
||||
parent = context.findAncestorStateOfType<_RingIndicatorState>();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(RingIndicator oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
_handleValueChange(widget.value, oldWidget.value);
|
||||
}
|
||||
|
||||
void updateValue(LevelValue value) {
|
||||
values[value.level] = value;
|
||||
if (parent != null && parent!.mounted) {
|
||||
for (var value in values.values) {
|
||||
parent!.updateValue(value.incrementLevel());
|
||||
}
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _RingIndicatorPainter extends CustomPainter {
|
||||
|
||||
Reference in New Issue
Block a user