import 'dart:async'; import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:flutter_ring_indicator/ring_indicator.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, brightness: Brightness.dark, ), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { double value1 = 30; double value2 = 50; double value3 = 10; List points = [0]; void _incrementCounter() { setState(() { value1 = Random().nextDouble() * 100; value2 = Random().nextDouble() * 100; value3 = Random().nextDouble() * 100; points.add(value2 - 20); if (points.length > 20) points.removeAt(0); }); } @override void initState() { Timer.periodic(const Duration(seconds: 1), (timer) => _incrementCounter()); super.initState(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox.square( dimension: 240, child: RingIndicator( ringColor: Colors.deepPurpleAccent, startAngel: pi * -0.7, endAngel: pi * 0.7, maxValue: 100, 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(1)?.toStringAsFixed(1) ?? '/'} ℃', style: const TextStyle(fontSize: 18)), Text('频率 ${((values.level(0) ?? 0) / 20).toStringAsFixed(1)} GHz', 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, ), ), ), ), const SizedBox(height: 50), SizedBox.square( dimension: 240, 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, ), ), ), ), const SizedBox(height: 50), SizedBox.square( dimension: 240, child: RingIndicator( ringColor: Colors.blueAccent, startAngel: -0.8 * pi, endAngel: 0.8 * pi, maxValue: 100, value: value2, labelBuilder: (values) => [ const Align( alignment: Alignment.bottomCenter, child: Text('占用率', style: TextStyle(fontSize: 28, height: 1.8)), ), Center( child: FractionallySizedBox( widthFactor: 0.8, heightFactor: 0.4, child: LineChart( LineChartData( maxX: 20, minX: 0, maxY: 50, minY: -50, lineBarsData: [ LineChartBarData( spots: [ ...List.generate(20 - points.length, (index) => FlSpot.nullSpot), ...points.reversed .toList() .asMap() .entries .map((e) => FlSpot(20 - e.key.toDouble(), e.value)), ].reversed.toList(), isCurved: true, dotData: FlDotData(show: false), barWidth: 3, belowBarData: BarAreaData( show: false, ), ), ], titlesData: FlTitlesData(show: false), borderData: FlBorderData(show: false), ), swapAnimationDuration: Duration.zero, ), ), ), ], ), ), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } }