123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- import 'dart:math' as math;
- import 'package:flutter/material.dart';
- import 'package:flutter/painting.dart';
- class CircularProgressBar extends StatefulWidget {
- final double percent;
- final double radius;
- final double width;
- final Widget? center;
- CircularProgressBar(
- {Key? key,
- this.percent = 0.0,
- this.radius = 50.0,
- this.width = 10.0,
- this.center});
- @override
- State<StatefulWidget> createState() => _State();
- }
- class _State extends State<CircularProgressBar>
- with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {
- late AnimationController _animationController;
- late Animation _animation;
- double _percent = 0.0;
- @override
- void dispose() {
- _animationController.dispose();
- super.dispose();
- }
- @override
- void initState() {
- _animationController = AnimationController(
- vsync: this, duration: Duration(milliseconds: 1000));
- _animation = Tween(begin: 0.0, end: widget.percent).animate(
- CurvedAnimation(parent: _animationController, curve: Curves.linear),
- )..addListener(() {
- setState(() {
- _percent = _animation.value;
- });
- });
- _animationController.addStatusListener((status) {});
- _animationController.forward();
- super.initState();
- }
- @override
- void didUpdateWidget(CircularProgressBar oldWidget) {
- super.didUpdateWidget(oldWidget);
- if (oldWidget.percent != widget.percent) {
- if (_animationController != null) {
- _animationController.duration = Duration(milliseconds: 1000);
- _animation = Tween(begin: 0.0, end: widget.percent).animate(
- CurvedAnimation(parent: _animationController, curve: Curves.linear),
- );
- _animationController.forward(from: 0.0);
- } else {
- _updateProgress();
- }
- }
- }
- _updateProgress() {
- setState(() {
- _percent = widget.percent;
- });
- }
- @override
- bool get wantKeepAlive => true;
- @override
- Widget build(BuildContext context) {
- super.build(context);
- return Container(
- height: widget.radius * 2 + widget.width,
- width: widget.radius * 2,
- child: AnimatedBuilder(
- animation: _animation,
- builder: (BuildContext context, Widget? child) {
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 10.0),
- child: CustomPaint(
- painter: ProgressBarThree(_animation.value,
- width: widget.width,
- radius: widget.radius - widget.width / 2),
- child: (widget.center != null)
- ? Center(child: widget.center)
- : Container(),
- ),
- );
- },
- ));
- }
- }
- class ProgressBarThree extends CustomPainter {
- final double progress;
- final double width;
- final double radius;
- final Paint _bg = Paint()
- ..isAntiAlias = true
- ..color = const Color(0xfff1f1f1)
- ..style = PaintingStyle.stroke;
- final List<Paint> _p = [
- Paint()
- ..isAntiAlias = true
- ..color = const Color(0xffFFE600)
- ..style = PaintingStyle.stroke,
- Paint()
- ..isAntiAlias = true
- ..color = const Color(0xffFFAA00)
- ..style = PaintingStyle.stroke,
- Paint()
- ..isAntiAlias = true
- ..color = const Color(0xffFF7323)
- ..style = PaintingStyle.stroke
- ];
- ProgressBarThree(this.progress, {this.width = 10.0, this.radius = 50.0});
- @override
- void paint(Canvas canvas, Size size) {
- final center = Offset(size.width / 2, size.height / 2);
- final rect = Rect.fromCircle(center: center, radius: this.radius);
- double max = math.pi * 2;
- double start = math.pi * 3 / 2;
- _bg.strokeWidth = width;
- int split = 3;
- double _angleEnd = max / split;
- double _endDiff = (_angleEnd - _angleEnd * 0.98) / 2;
- start += _endDiff;
- double _angle = start;
- for (var i = 0; i < split; i++) {
- canvas.drawArc(rect, _angle, _angleEnd * 0.98, false, _bg);
- _angle += _angleEnd;
- }
- double _progress = 1.0 / split;
- start = math.pi * 3 / 2;
- start += _endDiff;
- _angle = start;
- double _progressTotal = math.min(this.progress, 1.0);
- for (var i = 0; i < split; i++) {
- double _percent = _progressTotal / _progress;
- _p[i].strokeWidth = width;
- canvas.drawArc(rect, _angle, _angleEnd * 0.98 * math.min(_percent, 1.0),
- false, _p[i]);
- _angle += _angleEnd;
- _progressTotal -= _progress;
- if (_progressTotal < 0) break;
- }
- }
- @override
- bool shouldRepaint(CustomPainter oldDelegate) => this != oldDelegate;
- }
|