arc_progress_indicator.dart
3.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import 'dart:math' as Math;
import 'package:flutter/material.dart';
/// Draws an [ActionIcon] and [_ArcProgressPainter] that represent an active action.
/// As the provided [Animation] progresses the ActionArc grows into a full
/// circle and the ActionIcon moves along it.
class ArcProgressIndicator extends StatelessWidget {
// required
final Animation<double> controller;
final double radius;
// optional
final double startAngle;
final double? width;
/// The color to use when filling the arc.
///
/// Defaults to the accent color of the current theme.
final Color? color;
final IconData icon;
final Color? iconColor;
final double? iconSize;
// private
final Animation<double> _progress;
ArcProgressIndicator({
Key? key,
required this.controller,
required this.radius,
this.startAngle = 0.0,
this.width,
this.color,
required this.icon,
this.iconColor,
this.iconSize,
}) : _progress = Tween(begin: 0.0, end: 1.0).animate(controller),
super(key: key);
@override
Widget build(BuildContext context) {
late TextPainter _iconPainter;
final ThemeData theme = Theme.of(context);
final Color? _iconColor = iconColor ?? theme.colorScheme.secondary;
final double? _iconSize = iconSize ?? IconTheme.of(context).size;
_iconPainter = TextPainter(
textDirection: Directionality.of(context),
text: TextSpan(
text: String.fromCharCode(icon.codePoint),
style: TextStyle(
inherit: false,
color: _iconColor,
fontSize: _iconSize,
fontFamily: icon.fontFamily,
package: icon.fontPackage,
),
),
)..layout();
return CustomPaint(
painter: _ArcProgressPainter(
controller: _progress,
color: color ?? theme.colorScheme.secondary,
radius: radius,
width: width ?? _iconSize! * 2,
startAngle: startAngle,
icon: _iconPainter,
),
);
}
}
class _ArcProgressPainter extends CustomPainter {
// required
final Animation<double> controller;
final Color color;
final double radius;
final double width;
// optional
final double startAngle;
final TextPainter icon;
_ArcProgressPainter({
required this.controller,
required this.color,
required this.radius,
required this.width,
this.startAngle = 0.0,
required this.icon,
}) : super(repaint: controller);
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = color
..strokeWidth = width
..strokeCap = StrokeCap.round
..style = PaintingStyle.stroke;
final double sweepAngle = controller.value * 2 * Math.pi;
canvas.drawArc(
Offset.zero & size,
startAngle,
sweepAngle,
false,
paint,
);
double angle = startAngle + sweepAngle;
Offset offset = Offset(
(size.width / 2 - icon.size.width / 2) + radius * Math.cos(angle),
(size.height / 2 - icon.size.height / 2) + radius * Math.sin(angle),
);
icon.paint(canvas, offset);
}
@override
bool shouldRepaint(_ArcProgressPainter other) {
return controller.value != other.controller.value ||
color != other.color ||
radius != other.radius ||
width != other.width ||
startAngle != other.startAngle ||
icon != other.icon;
}
}