1+ //import 'package:flutter/material.dart';
2+ //import 'package:getflutter/getflutter.dart';
3+ //
4+ //class GFProgressIndicator extends StatefulWidget {
5+ // @override
6+ // _GFProgressIndicatorState createState() => _GFProgressIndicatorState();
7+ //}
8+ //
9+ //class _GFProgressIndicatorState extends State<GFProgressIndicator> {
10+ // @override
11+ // Widget build(BuildContext context) {
12+ // return Container();
13+ // }
14+ //}
15+
16+
117import 'package:flutter/material.dart' ;
2- import 'package:getflutter/getflutter.dart' ;
18+
19+ enum LinearStrokeCap { butt, round, roundAll }
320
421class GFProgressIndicator extends StatefulWidget {
22+ ///Percent value between 0.0 and 1.0
23+ final double percent;
24+ final double width;
25+
26+ ///Height of the line
27+ final double lineHeight;
28+
29+
30+ ///First color applied to the complete line
31+ final Color backgroundColor;
32+
33+ Color get progressColor => _progressColor;
34+
35+ Color _progressColor;
36+
37+ ///true if you want the Line to have animation
38+ final bool animation;
39+
40+ ///duration of the animation in milliseconds, It only applies if animation attribute is true
41+ final int animationDuration;
42+
43+ ///widget at the left of the Line
44+ final Widget leading;
45+
46+ ///widget at the right of the Line
47+ final Widget trailing;
48+
49+ ///widget inside the Line
50+ final Widget center;
51+
52+ ///The kind of finish to place on the end of lines drawn, values supported: butt, round, roundAll
53+ final LinearStrokeCap linearStrokeCap;
54+
55+ ///alignment of the Row (leading-widget-center-trailing)
56+ final MainAxisAlignment alignment;
57+
58+ ///padding to the GFProgressIndicator
59+ final EdgeInsets padding;
60+
61+ /// set true if you want to animate the linear from the last percent value you set
62+ final bool animateFromLastPercent;
63+
64+ /// If present, this will make the progress bar colored by this gradient.
65+ ///
66+ /// This will override [progressColor] . It is an error to provide both.
67+ final LinearGradient linearGradient;
68+
69+ /// set false if you don't want to preserve the state of the widget
70+ final bool addAutomaticKeepAlive;
71+
72+ /// set true if you want to animate the linear from the right to left (RTL)
73+ final bool isRTL;
74+
75+ /// Creates a mask filter that takes the progress shape being drawn and blurs it.
76+ final MaskFilter maskFilter;
77+
78+ /// Set true if you want to display only part of [linearGradient] based on percent value
79+ /// (ie. create 'VU effect'). If no [linearGradient] is specified this option is ignored.
80+ final bool clipLinearGradient;
81+
82+ GFProgressIndicator ({
83+ Key key,
84+ this .percent = 0.0 ,
85+ this .lineHeight = 5.0 ,
86+ this .width,
87+ this .backgroundColor = const Color (0xFFB8C7CB ),
88+ this .linearGradient,
89+ Color progressColor,
90+ this .animation = false ,
91+ this .animationDuration = 500 ,
92+ this .animateFromLastPercent = false ,
93+ this .isRTL = false ,
94+ this .leading,
95+ this .trailing,
96+ this .center,
97+ this .addAutomaticKeepAlive = true ,
98+ this .linearStrokeCap,
99+ this .padding = const EdgeInsets .symmetric (horizontal: 10.0 ),
100+ this .alignment = MainAxisAlignment .start,
101+ this .maskFilter,
102+ this .clipLinearGradient = false ,
103+ }) : super (key: key) {
104+ if (linearGradient != null && progressColor != null ) {
105+ throw ArgumentError (
106+ 'Cannot provide both linearGradient and progressColor' );
107+ }
108+ _progressColor = progressColor ?? Colors .red;
109+
110+ if (percent < 0.0 || percent > 1.0 ) {
111+ throw new Exception ("Percent value must be a double between 0.0 and 1.0" );
112+ }
113+ }
114+
5115 @override
6116 _GFProgressIndicatorState createState () => _GFProgressIndicatorState ();
7117}
8118
9- class _GFProgressIndicatorState extends State <GFProgressIndicator > {
119+ class _GFProgressIndicatorState extends State <GFProgressIndicator >
120+ with SingleTickerProviderStateMixin , AutomaticKeepAliveClientMixin {
121+ AnimationController _animationController;
122+ Animation _animation;
123+ double _percent = 0.0 ;
124+
125+ @override
126+ void dispose () {
127+ if (_animationController != null ) {
128+ _animationController.dispose ();
129+ }
130+ super .dispose ();
131+ }
132+
133+ @override
134+ void initState () {
135+ if (widget.animation) {
136+ _animationController = new AnimationController (
137+ vsync: this ,
138+ duration: Duration (milliseconds: widget.animationDuration));
139+ _animation =
140+ Tween (begin: 0.0 , end: widget.percent).animate (_animationController)
141+ ..addListener (() {
142+ setState (() {
143+ _percent = _animation.value;
144+ });
145+ });
146+ _animationController.forward ();
147+ } else {
148+ _updateProgress ();
149+ }
150+ super .initState ();
151+ }
152+
153+ @override
154+ void didUpdateWidget (GFProgressIndicator oldWidget) {
155+ super .didUpdateWidget (oldWidget);
156+ if (oldWidget.percent != widget.percent) {
157+ if (_animationController != null ) {
158+ _animationController.duration =
159+ Duration (milliseconds: widget.animationDuration);
160+ _animation = Tween (
161+ begin: widget.animateFromLastPercent ? oldWidget.percent : 0.0 ,
162+ end: widget.percent)
163+ .animate (_animationController);
164+ _animationController.forward (from: 0.0 );
165+ } else {
166+ _updateProgress ();
167+ }
168+ }
169+ }
170+
171+ _updateProgress () {
172+ setState (() {
173+ _percent = widget.percent;
174+ });
175+ }
176+
10177 @override
11178 Widget build (BuildContext context) {
12- return Container ();
179+ super .build (context);
180+ var items = List <Widget >();
181+ if (widget.leading != null ) {
182+ items.add (widget.leading);
183+ }
184+ final hasSetWidth = widget.width != null ;
185+ var containerWidget = Container (
186+ width: hasSetWidth ? widget.width : double .infinity,
187+ height: widget.lineHeight,
188+ padding: widget.padding,
189+ child: CustomPaint (
190+ painter: LinearPainter (
191+ isRTL: widget.isRTL,
192+ progress: _percent,
193+ center: widget.center,
194+ progressColor: widget.progressColor,
195+ linearGradient: widget.linearGradient,
196+ backgroundColor: widget.backgroundColor,
197+ linearStrokeCap: widget.linearStrokeCap,
198+ lineWidth: widget.lineHeight,
199+ maskFilter: widget.maskFilter,
200+ clipLinearGradient: widget.clipLinearGradient,
201+ ),
202+ child: (widget.center != null )
203+ ? Center (child: widget.center)
204+ : Container (),
205+ ),
206+ );
207+
208+ if (hasSetWidth) {
209+ items.add (containerWidget);
210+ } else {
211+ items.add (Expanded (
212+ child: containerWidget,
213+ ));
214+ }
215+ if (widget.trailing != null ) {
216+ items.add (widget.trailing);
217+ }
218+
219+ return Material (
220+ color: Colors .transparent,
221+ child: new Container (
222+ child: Row (
223+ mainAxisAlignment: widget.alignment,
224+ crossAxisAlignment: CrossAxisAlignment .center,
225+ children: items,
226+ )),
227+ );
13228 }
229+
230+ @override
231+ bool get wantKeepAlive => widget.addAutomaticKeepAlive;
14232}
233+
234+ class LinearPainter extends CustomPainter {
235+ final Paint _paintBackground = new Paint ();
236+ final Paint _paintLine = new Paint ();
237+ final lineWidth;
238+ final progress;
239+ final center;
240+ final isRTL;
241+ final Color progressColor;
242+ final Color backgroundColor;
243+ final LinearStrokeCap linearStrokeCap;
244+ final LinearGradient linearGradient;
245+ final MaskFilter maskFilter;
246+ final bool clipLinearGradient;
247+
248+ LinearPainter ({
249+ this .lineWidth,
250+ this .progress,
251+ this .center,
252+ this .isRTL,
253+ this .progressColor,
254+ this .backgroundColor,
255+ this .linearStrokeCap = LinearStrokeCap .butt,
256+ this .linearGradient,
257+ this .maskFilter,
258+ this .clipLinearGradient,
259+ }) {
260+ _paintBackground.color = backgroundColor;
261+ _paintBackground.style = PaintingStyle .stroke;
262+ _paintBackground.strokeWidth = lineWidth;
263+
264+ _paintLine.color = progress.toString () == "0.0"
265+ ? progressColor.withOpacity (0.0 )
266+ : progressColor;
267+ _paintLine.style = PaintingStyle .stroke;
268+ _paintLine.strokeWidth = lineWidth;
269+
270+ if (linearStrokeCap == LinearStrokeCap .round) {
271+ _paintLine.strokeCap = StrokeCap .round;
272+ } else if (linearStrokeCap == LinearStrokeCap .butt) {
273+ _paintLine.strokeCap = StrokeCap .butt;
274+ } else {
275+ _paintLine.strokeCap = StrokeCap .round;
276+ _paintBackground.strokeCap = StrokeCap .round;
277+ }
278+ }
279+
280+ @override
281+ void paint (Canvas canvas, Size size) {
282+ final start = Offset (0.0 , size.height / 2 );
283+ final end = Offset (size.width, size.height / 2 );
284+ canvas.drawLine (start, end, _paintBackground);
285+
286+ if (maskFilter != null ) {
287+ _paintLine.maskFilter = maskFilter;
288+ }
289+
290+ if (isRTL) {
291+ final xProgress = size.width - size.width * progress;
292+ if (linearGradient != null ) {
293+ _paintLine.shader = _createGradientShaderRightToLeft (size, xProgress);
294+ }
295+ canvas.drawLine (end, Offset (xProgress, size.height / 2 ), _paintLine);
296+ } else {
297+ final xProgress = size.width * progress;
298+ if (linearGradient != null ) {
299+ _paintLine.shader = _createGradientShaderLeftToRight (size, xProgress);
300+ }
301+ canvas.drawLine (start, Offset (xProgress, size.height / 2 ), _paintLine);
302+ }
303+ }
304+
305+ Shader _createGradientShaderRightToLeft (Size size, double xProgress) {
306+ Offset shaderEndPoint =
307+ clipLinearGradient ? Offset .zero : Offset (xProgress, size.height);
308+ return linearGradient.createShader (
309+ Rect .fromPoints (
310+ Offset (size.width, size.height),
311+ shaderEndPoint,
312+ ),
313+ );
314+ }
315+
316+ Shader _createGradientShaderLeftToRight (Size size, double xProgress) {
317+ Offset shaderEndPoint = clipLinearGradient
318+ ? Offset (size.width, size.height)
319+ : Offset (xProgress, size.height);
320+ return linearGradient.createShader (
321+ Rect .fromPoints (
322+ Offset .zero,
323+ shaderEndPoint,
324+ ),
325+ );
326+ }
327+
328+ @override
329+ bool shouldRepaint (CustomPainter oldDelegate) {
330+ return true ;
331+ }
332+ }
0 commit comments