11import 'package:flutter/material.dart' ;
22import 'package:flutter/rendering.dart' ;
3+ import 'package:getflutter/getflutter.dart' ;
34
45enum GFShimmerDirection { leftToRight, rightToLeft, topToBottom, bottomToTop }
56
@@ -11,10 +12,38 @@ class GFShimmer extends StatefulWidget {
1112 @required this .gradient,
1213 this .direction = GFShimmerDirection .leftToRight,
1314 this .duration = const Duration (milliseconds: 1500 ),
14- this .loop = 0 ,
15- this .enabled = true ,
15+ this .shimmerEffectCount = 0 ,
16+ this .showShimmerEffect = true ,
1617 }) : super (key: key);
1718
19+ GFShimmer .withColors ({
20+ Key key,
21+ @required this .child,
22+ dynamic baseColor = GFColor .primary,
23+ dynamic highlightColor = GFColor .light,
24+ this .direction = GFShimmerDirection .leftToRight,
25+ this .duration = const Duration (milliseconds: 1500 ),
26+ this .shimmerEffectCount = 0 ,
27+ this .showShimmerEffect = true ,
28+ }) : gradient = LinearGradient (
29+ begin: Alignment .topLeft,
30+ end: Alignment .centerRight,
31+ colors: < Color > [
32+ GFColors .getGFColor (baseColor),
33+ GFColors .getGFColor (baseColor),
34+ GFColors .getGFColor (highlightColor),
35+ GFColors .getGFColor (baseColor),
36+ GFColors .getGFColor (baseColor)
37+ ],
38+ stops: const < double > [
39+ 0 ,
40+ 0.3 ,
41+ 0.5 ,
42+ 0.7 ,
43+ 1
44+ ]),
45+ super (key: key);
46+
1847 /// The widget below this widget in the tree.
1948 final Widget child;
2049
@@ -27,11 +56,17 @@ class GFShimmer extends StatefulWidget {
2756 /// Controls the [child] 's shades of color.
2857 final Gradient gradient;
2958
30- /// Controls the animation loop . The default value is '0', that makes animation forever.
31- final int loop ;
59+ /// Controls the animation shimmerEffectCount . The default value is '0', that makes animation forever.
60+ final int shimmerEffectCount ;
3261
3362 /// Controls animation effect, defaults true state that makes animation active.
34- final bool enabled;
63+ final bool showShimmerEffect;
64+
65+ /// defines the base color of the [child] 's shimmer effect.
66+ /// dynamic baseColor;
67+
68+ /// defines the highLight color of the [child] 's shimmer effect.
69+ /// dynamic highLightColor;
3570
3671 @override
3772 _GFShimmerState createState () => _GFShimmerState ();
@@ -52,20 +87,20 @@ class _GFShimmerState extends State<GFShimmer>
5287 return ;
5388 }
5489 _count++ ;
55- if (widget.loop <= 0 ) {
90+ if (widget.shimmerEffectCount <= 0 ) {
5691 _controller.repeat ();
57- } else if (_count < widget.loop ) {
92+ } else if (_count < widget.shimmerEffectCount ) {
5893 _controller.forward (from: 0 );
5994 }
6095 });
61- if (widget.enabled ) {
96+ if (widget.showShimmerEffect ) {
6297 _controller.forward ();
6398 }
6499 }
65100
66101 @override
67102 void didUpdateWidget (GFShimmer oldWidget) {
68- if (widget.enabled ) {
103+ if (widget.showShimmerEffect ) {
69104 _controller.forward ();
70105 } else {
71106 _controller.stop ();
@@ -77,9 +112,12 @@ class _GFShimmerState extends State<GFShimmer>
77112 Widget build (BuildContext context) => AnimatedBuilder (
78113 animation: _controller,
79114 child: widget.child,
80- builder: (BuildContext context, Widget child) => Transform .rotate (
81- angle: _controller.value * 2.0 * 22 / 7 ,
115+ builder: (BuildContext context, Widget child) => _GFShimmer (
82116 child: child,
117+ direction: widget.direction,
118+ gradient: widget.gradient,
119+ controllerValue: _controller.value,
120+ showShimmerEffect: widget.showShimmerEffect,
83121 ),
84122 );
85123
@@ -89,3 +127,122 @@ class _GFShimmerState extends State<GFShimmer>
89127 super .dispose ();
90128 }
91129}
130+
131+ @immutable
132+ class _GFShimmer extends SingleChildRenderObjectWidget {
133+ const _GFShimmer ({
134+ Widget child,
135+ this .controllerValue,
136+ this .direction,
137+ this .gradient,
138+ this .showShimmerEffect,
139+ }) : super (child: child);
140+
141+ /// value that controls the animation controller
142+ final double controllerValue;
143+
144+ /// Controls the direction of the shimmer effect. The default value is GFShimmerDirection.leftToRight.
145+ final GFShimmerDirection direction;
146+
147+ /// Controls the [child] 's shades of color.
148+ final Gradient gradient;
149+
150+ /// Controls animation effect, defaults true state that makes animation active.
151+ final bool showShimmerEffect;
152+
153+ @override
154+ GFShimmerFilter createRenderObject (BuildContext context) => GFShimmerFilter (
155+ value: controllerValue,
156+ direction: direction,
157+ gradient: gradient,
158+ showShimmerEffect: showShimmerEffect);
159+
160+ @override
161+ void updateRenderObject (BuildContext context, GFShimmerFilter shimmer) {
162+ shimmer.controllerValue = controllerValue;
163+ shimmer.showShimmerEffect = showShimmerEffect;
164+ }
165+ }
166+
167+ class GFShimmerFilter extends RenderProxyBox {
168+ GFShimmerFilter (
169+ {this .value, this .direction, this .gradient, this .showShimmerEffect})
170+ : gradientPaint = Paint ()..blendMode = BlendMode .srcIn;
171+
172+ /// Constructs an empty [Paint] object with all fields initialized to their defaults.
173+ final Paint initialPaint = Paint ();
174+
175+ /// Shader that paints a color gradient.
176+ final Paint gradientPaint;
177+
178+ /// Controls the [child] 's shades of color.
179+ final Gradient gradient;
180+
181+ /// Controls the direction of the shimmer effect. The default value is GFShimmerDirection.leftToRight.
182+ final GFShimmerDirection direction;
183+
184+ /// Controls animation effect, defaults true state that makes animation active.
185+ bool showShimmerEffect;
186+
187+ /// value that controls the animation controller
188+ double value;
189+
190+ /// Construct a rectangle from its left, top, right, and bottom edges.
191+ Rect _rect;
192+
193+ @override
194+ bool get alwaysNeedsCompositing => child != null ;
195+
196+ double get controllerValue => value;
197+
198+ set controllerValue (double newValue) {
199+ if (newValue == value) {
200+ return ;
201+ }
202+ value = newValue;
203+ markNeedsPaint ();
204+ }
205+
206+ @override
207+ void paint (PaintingContext context, Offset offset) {
208+ if (child == null ) {
209+ return ;
210+ }
211+ assert (needsCompositing);
212+
213+ context.canvas.saveLayer (offset & child.size, initialPaint);
214+ context.paintChild (child, offset);
215+ Rect rect;
216+ double dx, dy;
217+ final double width = child.size.width;
218+ final double height = child.size.height;
219+
220+ if (direction == GFShimmerDirection .rightToLeft) {
221+ dx = _offset (width, - width, value);
222+ dy = 0.0 ;
223+ rect = Rect .fromLTWH (offset.dx - width, offset.dy, 3 * width, height);
224+ } else if (direction == GFShimmerDirection .bottomToTop) {
225+ dx = 0.0 ;
226+ dy = _offset (height, - height, value);
227+ rect = Rect .fromLTWH (offset.dx, offset.dy - height, width, 3 * height);
228+ } else if (direction == GFShimmerDirection .topToBottom) {
229+ dx = 0.0 ;
230+ dy = _offset (- height, height, value);
231+ rect = Rect .fromLTWH (offset.dx, offset.dy - height, width, 3 * height);
232+ } else {
233+ dx = _offset (- width, width, value);
234+ dy = 0.0 ;
235+ rect = Rect .fromLTWH (offset.dx - width, offset.dy, 3 * width, height);
236+ }
237+ if (_rect != rect) {
238+ gradientPaint.shader = gradient.createShader (rect);
239+ _rect = rect;
240+ }
241+ context.canvas.translate (dx, dy);
242+ context.canvas.drawRect (rect, gradientPaint);
243+ context.canvas.restore ();
244+ }
245+
246+ double _offset (double start, double end, double controllerValue) =>
247+ start + (end - start) * controllerValue;
248+ }
0 commit comments