10 | * Created by Eudy Contreras 11 | * 12 | * @author Eudy Contreras 13 | * @version 1.0 14 | * @since 2018-03-31 15 | */ 16 | @RestrictTo(RestrictTo.Scope.LIBRARY) 17 | public class Bounds { 18 | 19 | private final float x; 20 | private final float y; 21 | 22 | private final float width; 23 | private final float height; 24 | 25 | public Bounds(float x, float y, float width, float height) { 26 | this.x = x; 27 | this.y = y; 28 | this.width = width; 29 | this.height = height; 30 | } 31 | 32 | public float getX() { 33 | return x; 34 | } 35 | 36 | public float getY() { 37 | return y; 38 | } 39 | 40 | public float getWidth() { 41 | return width; 42 | } 43 | 44 | public float getHeight() { 45 | return height; 46 | } 47 | 48 | public boolean inRange(float sourceX, float sourceY){ 49 | return (sourceX >= x && sourceX < width) && (sourceY >= y && sourceY < height); 50 | } 51 | 52 | public boolean inRange(float sourceX, float sourceY, float radius){ 53 | return (sourceX >= (x-radius) && sourceX < (width + radius)) && (sourceY >= (y-radius) && sourceY < (height + radius)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /indicatoreffectlib/src/main/java/com/eudycontreras/indicatoreffectlib/Property.java: -------------------------------------------------------------------------------- 1 | package com.eudycontreras.indicatoreffectlib; 2 | 3 | import androidx.annotation.RestrictTo; 4 | 5 | /** 6 | * Note: Unlicensed private property of the author and creator 7 | * unauthorized use of this class outside of the Indicator Effect project 8 | * by the author may result on legal prosecution. 9 | *
10 | * Created by Eudy Contreras
11 | *
12 | * @author Eudy Contreras
13 | * @version 1.0
14 | * @since 2018-03-31
15 | */
16 | @RestrictTo(RestrictTo.Scope.LIBRARY)
17 | public class Property
14 | * Created by Eudy Contreras
15 | *
16 | * @author Eudy Contreras
17 | * @version 1.0
18 | * @since 2018-03-31
19 | */
20 | @RestrictTo(RestrictTo.Scope.LIBRARY)
21 | public abstract class Particle {
22 |
23 | public final static float DEFAULT_LIFE_TIME = 5;
24 | public final static float DEFAULT_VELOCITY = 5;
25 |
26 | protected float centerX;
27 | protected float centerY;
28 |
29 | protected float targetX = Integer.MIN_VALUE;
30 | protected float targetY = Integer.MIN_VALUE;
31 |
32 | protected float velX;
33 | protected float velY;
34 |
35 | protected float varianceX;
36 | protected float varianceY;
37 |
38 | protected float radiusRatio = 0.0f;
39 | protected float actualRadius;
40 | protected float radius;
41 | protected float spacing;
42 | protected float opacity = 1.0f;
43 |
44 | protected float lifeSpan = 1.0f;
45 | protected float decay;
46 |
47 | protected boolean visible;
48 | protected boolean killed;
49 | protected boolean fade = true;
50 | protected boolean shrink = true;
51 | protected boolean checkBounds = false;
52 | protected boolean alwaysAlive = false;
53 |
54 | protected Bounds bounds;
55 | protected Paint paint;
56 |
57 | protected ColorUtility.SoulColor color;
58 | protected ColorUtility.SoulColor colorStart;
59 | protected ColorUtility.SoulColor colorEnd;
60 | protected ColorUtility.SoulColor strokeColor;
61 | protected ColorUtility.SoulColor innerOutlineColor;
62 |
63 | protected Particle(float lifeTime, float x, float y, float velX, float velY, float varianceX, float varianceY, float radius, int color, Paint paint, Bounds bounds) {
64 | this.centerX = x;
65 | this.centerY = y;
66 | this.velX = velX;
67 | this.velY = velY;
68 | this.varianceX = varianceX;
69 | this.varianceY = varianceY;
70 | this.radius = radius;
71 | this.color = ColorUtility.toSoulColor(color);
72 | this.bounds = bounds;
73 | this.decay = 0.016f / lifeTime;
74 | this.paint = paint;
75 | }
76 |
77 | protected Particle(float lifeTime, float x, float y, float velX, float velY, float radius, int color, Paint paint, Bounds bounds) {
78 | this(lifeTime, x, y, velX, velY, 0, 0, radius, color, paint, bounds);
79 | }
80 |
81 | protected Particle(float lifeTime, float x, float y, float radius, int color, Paint paint, Bounds bounds) {
82 | this(lifeTime, x, y,0, 0, radius, color,paint, bounds);
83 | }
84 |
85 | protected Particle(float x, float y, float radius, int color, Paint paint, Bounds bounds) {
86 | this(Integer.MAX_VALUE, x, y,0, 0, radius, color,paint, bounds);
87 | }
88 |
89 | protected Particle(float x, float y, float radius, int color, Bounds bounds) {
90 | this(Integer.MAX_VALUE, x, y,0, 0, radius, color,new Paint(), bounds);
91 | }
92 |
93 | public abstract void init();
94 |
95 | protected abstract void draw(Canvas canvas);
96 |
97 | public void update(){
98 | centerX += (velX + varianceX);
99 | centerY += (velY + varianceY);
100 |
101 | if(killed) {
102 | lifeSpan -= decay;
103 | }
104 | }
105 |
106 | public void update(float duration, float time){
107 |
108 | velX = targetX != Integer.MIN_VALUE ? ((targetX - centerX) / duration) : velX;
109 | velY = targetY != Integer.MIN_VALUE ? ((targetY - centerY) / duration) : velY;
110 |
111 | centerX += ((velX + varianceX) * time);
112 | centerY += ((velY + varianceY) * time);
113 |
114 | if(shrink){
115 | radiusRatio = time;
116 | radius = actualRadius * radiusRatio;
117 | }
118 |
119 | if(killed) {
120 | lifeSpan -= (decay * time);
121 | }else{
122 | if(fade) {
123 | opacity = time;
124 | }
125 | }
126 | }
127 |
128 | public float checkDistanceTo(Particle particle) {
129 |
130 | float distanceX = this.centerX+radius - particle.getCenterX()+radius;
131 | float distanceY = this.centerY+radius - particle.getCenterY()+radius;
132 |
133 | return distanceX*distanceX + distanceY*distanceY;
134 | }
135 |
136 | public boolean isAlive() {
137 | if(alwaysAlive){
138 | return true;
139 | }else{
140 | if(bounds != null) {
141 | return (!checkBounds || bounds.inRange(centerX, centerY, (radius * 2))) && (lifeSpan > 0) && (radius > 0) && (opacity > 0);
142 | }
143 | return lifeSpan > 0;
144 | }
145 | }
146 |
147 | public Paint getPaint() {
148 | return paint;
149 | }
150 |
151 | public void setVisible(boolean visible) {
152 | this.visible = visible;
153 | }
154 |
155 | public boolean isVisible() {
156 | return visible;
157 | }
158 |
159 | public boolean isFade() {
160 | return fade;
161 | }
162 |
163 | public void setFade(boolean fade) {
164 | this.fade = fade;
165 | }
166 |
167 | public float getOpacity() {
168 | return opacity;
169 | }
170 |
171 | public void setOpacity(float opacity) {
172 | this.opacity = opacity;
173 | }
174 |
175 | public boolean isShrink() {
176 | return shrink;
177 | }
178 |
179 | public void setShrink(boolean shrink) {
180 | this.shrink = shrink;
181 | }
182 |
183 | public float getTargetX() {
184 | return targetX;
185 | }
186 |
187 | public void setTargetX(float targetX) {
188 | this.targetX = targetX;
189 | }
190 |
191 | public float getTargetY() {
192 | return targetY;
193 | }
194 |
195 | public void setTargetY(float targetY) {
196 | this.targetY = targetY;
197 | }
198 |
199 | public float getCenterX() {
200 | return centerX;
201 | }
202 |
203 | public void setCenterX(float centerX) {
204 | this.centerX = centerX;
205 | }
206 |
207 | public float getCenterY() {
208 | return centerY;
209 | }
210 |
211 | public void setCenterY(float centerY) {
212 | this.centerY = centerY;
213 | }
214 |
215 | public float getVelX() {
216 | return velX;
217 | }
218 |
219 | public void setVelX(float velX) {
220 | this.velX = velX;
221 | }
222 |
223 | public float getVelY() {
224 | return velY;
225 | }
226 |
227 | public void setVelY(float velY) {
228 | this.velY = velY;
229 | }
230 |
231 | public float getVarianceX() {
232 | return varianceX;
233 | }
234 |
235 | public void setVarianceX(float varianceX) {
236 | this.varianceX = varianceX;
237 | }
238 |
239 | public float getVarianceY() {
240 | return varianceY;
241 | }
242 |
243 | public void setVarianceY(float varianceY) {
244 | this.varianceY = varianceY;
245 | }
246 |
247 | public float getRadius() {
248 | return radius;
249 | }
250 |
251 | public void setRadius(float radius) {
252 | this.radius = radius;
253 | this.actualRadius = radius;
254 | }
255 |
256 | public ColorUtility.SoulColor getColor() {
257 | return color;
258 | }
259 |
260 | public void setColor(ColorUtility.SoulColor color) {
261 | this.color = color;
262 | }
263 |
264 | public void setStrokeColor(ColorUtility.SoulColor color) {
265 | this.strokeColor = color;
266 | }
267 |
268 | public void setInnerOutlineColor(ColorUtility.SoulColor innerOutlineColor) {
269 | this.innerOutlineColor = innerOutlineColor;
270 | }
271 |
272 | public ColorUtility.SoulColor getStrokeColor() {
273 | return strokeColor;
274 | }
275 |
276 | public ColorUtility.SoulColor getColorStart() {
277 | return colorStart;
278 | }
279 |
280 | public void setColorStart(ColorUtility.SoulColor colorStart) {
281 | this.colorStart = colorStart;
282 | }
283 |
284 | public ColorUtility.SoulColor getColorEnd() {
285 | return colorEnd;
286 | }
287 |
288 | public void setColorEnd(ColorUtility.SoulColor colorEnd) {
289 | this.colorEnd = colorEnd;
290 | }
291 |
292 | public float getDecay() {
293 | return decay;
294 | }
295 |
296 | public void setDecay(float decay) {
297 | this.decay = 0.016f / decay;
298 | }
299 |
300 | public Bounds getBounds() {
301 | return bounds;
302 | }
303 |
304 | public void setBounds(Bounds bounds) {
305 | this.bounds = bounds;
306 | }
307 |
308 | public void setPaint(Paint paint) {
309 | this.paint = paint;
310 | }
311 |
312 | public boolean isKilled() {
313 | return killed;
314 | }
315 |
316 | public void setKilled(boolean killed) {
317 | this.killed = killed;
318 | }
319 |
320 | public boolean isCheckBounds() {
321 | return checkBounds;
322 | }
323 |
324 | public void setCheckBounds(boolean checkBounds) {
325 | this.checkBounds = checkBounds;
326 | }
327 |
328 | public boolean isAlwaysAlive() {
329 | return alwaysAlive;
330 | }
331 |
332 | public void setAlwaysAlive(boolean alwaysAlive) {
333 | this.alwaysAlive = alwaysAlive;
334 | }
335 |
336 | public void setSpacing(float spacing) {
337 | this.spacing = spacing;
338 | }
339 |
340 | public float getSpacing(){
341 | return spacing;
342 | }
343 | }
344 |
--------------------------------------------------------------------------------
/indicatoreffectlib/src/main/java/com/eudycontreras/indicatoreffectlib/particles/ParticleIndicator.java:
--------------------------------------------------------------------------------
1 | package com.eudycontreras.indicatoreffectlib.particles;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.graphics.Path;
7 | import android.graphics.Region;
8 | import android.os.Build;
9 | import androidx.annotation.RestrictTo;
10 | import com.eudycontreras.indicatoreffectlib.Bounds;
11 | import com.eudycontreras.indicatoreffectlib.utilities.ColorUtility;
12 | import com.eudycontreras.indicatoreffectlib.views.IndicatorView;
13 |
14 | /**
15 | * Note: Unlicensed private property of the author and creator
16 | * unauthorized use of this class outside of the Indicator Effect project
17 | * by the author may result on legal prosecution.
18 | *
19 | * Created by Eudy Contreras
20 | *
21 | * @author Eudy Contreras
22 | * @version 1.0
23 | * @since 2018-03-31
24 | */
25 | @RestrictTo(RestrictTo.Scope.LIBRARY)
26 | public class ParticleIndicator extends Particle {
27 |
28 | public static final int RIPPLE_TYPE_OUTLINE = 0;
29 | public static final int RIPPLE_TYPE_FILLED = 1;
30 | public static final int RIPPLE_TYPE_INDICATOR = 2;
31 |
32 | private float cornerRadius = 0;
33 |
34 | private float x;
35 | private float y;
36 |
37 | private float width;
38 | private float height;
39 |
40 | private float maxWidth;
41 | private float maxHeight;
42 |
43 | private float minWidth;
44 | private float minHeight;
45 |
46 | private float maxRadius;
47 | private float minRadius;
48 |
49 | private float minOpacity;
50 | private float maxOpacity;
51 |
52 | private float clipRadius;
53 |
54 | private float clipWidhtRatio;
55 | private float clipHeightRatio;
56 |
57 | private float strokeWidth;
58 |
59 | private float innerOutlineWidth;
60 |
61 | private float interpolation;
62 |
63 | private int shapeType;
64 | private int type;
65 |
66 | private Path clipPath;
67 |
68 | public ParticleIndicator() {
69 | super(0, 0, 0, 0, null, null);
70 | }
71 |
72 | public ParticleIndicator(float x, float y, float radius, int color, Paint paint, Bounds bounds) {
73 | super(x, y, radius, color, paint, bounds);
74 | }
75 |
76 | public ParticleIndicator(float x, float y, float radius, int color, Bounds bounds) {
77 | super(x, y, radius, color, bounds);
78 | }
79 |
80 | public void init() {
81 | clipPath = new Path();
82 | clipPath.reset();
83 | if (shapeType == IndicatorView.INDICATOR_SHAPE_CIRCLE) {
84 | clipPath.addCircle(centerX, centerY, clipRadius, Path.Direction.CCW);
85 | } else {
86 | float top = y - (minHeight / 2);
87 | float left = x - (minWidth / 2);
88 | float bottom = y + (minHeight / 2);
89 | float right = x + (minWidth / 2);
90 | clipPath.addRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, Path.Direction.CCW);
91 | }
92 | }
93 |
94 | @Override
95 | public void update() {
96 |
97 | }
98 |
99 | @Override
100 | public void update(float duration, float time) {
101 | if (shapeType == IndicatorView.INDICATOR_SHAPE_CIRCLE) {
102 | radius = minRadius + ((maxRadius - minRadius) * time);
103 | } else {
104 | width = minWidth + ((maxWidth - minWidth) * time);
105 | height = minHeight + ((maxHeight - minHeight) * time);
106 |
107 | x = x - (width / 2);
108 | y = y - (height / 2);
109 | }
110 |
111 | opacity = minOpacity + ((maxOpacity - minOpacity) * (maxOpacity - minOpacity - time));
112 |
113 | if (opacity < 0f)
114 | opacity = 0f;
115 | if (opacity > 1f)
116 | opacity = 1f;
117 |
118 | if (colorStart != null && colorEnd != null) {
119 | ColorUtility.interpolateColor(colorStart, colorEnd, time, color);
120 | }
121 | }
122 |
123 | @Override
124 | public boolean isAlive() {
125 | return (opacity > 0f && (radius > 0 || width > 0 || height > 0)) || alwaysAlive;
126 | }
127 |
128 | public void draw(Canvas canvas) {
129 | switch (type) {
130 | case RIPPLE_TYPE_FILLED:
131 | drawFilledRipple(canvas);
132 | break;
133 | case RIPPLE_TYPE_INDICATOR:
134 | drawIndicatorRipple(canvas);
135 | break;
136 | case RIPPLE_TYPE_OUTLINE:
137 | drawOutLineRipple(canvas);
138 | break;
139 | }
140 |
141 | if (innerOutlineColor != null) {
142 | paint.setStyle(Paint.Style.STROKE);
143 | paint.setStrokeWidth(innerOutlineWidth);
144 | paint.setColor(innerOutlineColor.toColor());
145 |
146 | canvas.drawCircle(centerX, centerY, minRadius, paint);
147 | }
148 | }
149 |
150 | private void drawFilledRipple(Canvas canvas) {
151 | color.setAlpha(opacity);
152 |
153 | paint.setStyle(Paint.Style.FILL);
154 | paint.setColor(color.toColor());
155 |
156 | if (shapeType == IndicatorView.INDICATOR_SHAPE_CIRCLE) {
157 | canvas.drawCircle(centerX, centerY, radius, paint);
158 |
159 | if (strokeColor != null) {
160 | strokeColor.setAlpha(opacity);
161 |
162 | paint.setStyle(Paint.Style.STROKE);
163 | paint.setStrokeWidth(strokeWidth);
164 | paint.setColor(strokeColor.toColor());
165 |
166 | canvas.drawCircle(centerX, centerY, radius, paint);
167 | }
168 |
169 | } else {
170 | float top = y;
171 | float left = x;
172 | float bottom = y + height;
173 | float right = x + width;
174 | canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, paint);
175 | }
176 | }
177 |
178 | private void drawOutLineRipple(Canvas canvas) {
179 | color.setAlpha(opacity);
180 |
181 | paint.setStyle(Paint.Style.STROKE);
182 | paint.setStrokeWidth(strokeWidth);
183 | paint.setColor(color.toColor());
184 |
185 | if (shapeType == IndicatorView.INDICATOR_SHAPE_CIRCLE) {
186 | canvas.drawCircle(centerX, centerY, radius, paint);
187 | } else {
188 | float top = y;
189 | float left = x;
190 | float bottom = y + height;
191 | float right = x + width;
192 | canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, paint);
193 | }
194 | }
195 |
196 | @SuppressWarnings("Deprecated")
197 | @SuppressLint("Deprecated")
198 | private void drawIndicatorRipple(Canvas canvas) {
199 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
200 | canvas.clipOutPath(clipPath);
201 | } else {
202 | canvas.clipPath(clipPath, Region.Op.DIFFERENCE);
203 | }
204 |
205 | color.setAlpha(opacity);
206 |
207 | paint.setStyle(Paint.Style.FILL);
208 | paint.setColor(color.toColor());
209 |
210 | if (shapeType == IndicatorView.INDICATOR_SHAPE_CIRCLE) {
211 | canvas.drawCircle(centerX, centerY, radius, paint);
212 |
213 | if (strokeColor != null) {
214 | strokeColor.setAlpha(opacity);
215 |
216 | paint.setStyle(Paint.Style.STROKE);
217 | paint.setStrokeWidth(strokeWidth);
218 | paint.setColor(strokeColor.toColor());
219 |
220 | canvas.drawCircle(centerX, centerY, radius, paint);
221 | }
222 |
223 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
224 | canvas.clipOutPath(clipPath);
225 | } else {
226 | canvas.clipPath(clipPath, Region.Op.DIFFERENCE);
227 | }
228 | } else {
229 | float top = y;
230 | float left = x;
231 | float bottom = y + height;
232 | float right = x + width;
233 | canvas.drawRoundRect(left, top, right, bottom, cornerRadius, cornerRadius, paint);
234 | }
235 | }
236 |
237 | public void setMinRadius(float minRadius) {
238 | this.minRadius = minRadius;
239 | }
240 |
241 | public void setMaxRadius(float maxRadius) {
242 | this.maxRadius = maxRadius;
243 | }
244 |
245 | public void setMinOpacity(float minOpacity) {
246 | this.minOpacity = minOpacity;
247 | }
248 |
249 | public void setMaxOpacity(float minOpacity) {
250 | this.maxOpacity = minOpacity;
251 | }
252 |
253 | public void setClipRadius(float clipRadius) {
254 | this.clipRadius = clipRadius;
255 | }
256 |
257 | public void setType(int type) {
258 | this.type = type;
259 | }
260 |
261 | public void setStrokeWidth(float strokeWidth) {
262 | this.strokeWidth = strokeWidth;
263 | }
264 |
265 | public void setInnerOutlineWidth(float innerOutlineWidth) {
266 | this.innerOutlineWidth = innerOutlineWidth;
267 | }
268 |
269 | public void setCornerRadius(float cornerRadius) {
270 | this.cornerRadius = cornerRadius;
271 | }
272 |
273 | public void setShapeType(int shapeType) {
274 | this.shapeType = shapeType;
275 | }
276 |
277 | public void setMaxWidth(float width) {
278 | this.maxWidth = width;
279 | }
280 |
281 | public void setMaxHeight(float height) {
282 | this.maxHeight = height;
283 | }
284 |
285 | public void setMinWidth(float width) {
286 | this.minWidth = width;
287 | }
288 |
289 | public void setMinHeight(float height) {
290 | this.minHeight = height;
291 | }
292 |
293 | public void setY(float y) {
294 | this.y = y;
295 | }
296 |
297 | public void setX(float x) {
298 | this.x = x;
299 | }
300 | }
301 |
--------------------------------------------------------------------------------
/indicatoreffectlib/src/main/java/com/eudycontreras/indicatoreffectlib/utilities/ColorUtility.java:
--------------------------------------------------------------------------------
1 | package com.eudycontreras.indicatoreffectlib.utilities;
2 |
3 | import android.graphics.Color;
4 | import androidx.annotation.ColorInt;
5 | import androidx.annotation.RestrictTo;
6 |
7 | /**
8 | * Note: Unlicensed private property of the author and creator
9 | * unauthorized use of this class outside of the Indicator Effect project
10 | * by the author may result on legal prosecution.
11 | *
12 | * Created by Eudy Contreras
13 | *
14 | * @author Eudy Contreras
15 | * @version 1.0
16 | * @since 2018-03-31
17 | */
18 | @RestrictTo(RestrictTo.Scope.LIBRARY)
19 | public class ColorUtility {
20 |
21 | public static int colorDecToHex(int r, int g, int b) {
22 | return Color.parseColor(colorDecToHexString(r, g, b));
23 | }
24 |
25 | public static int colorDecToHex(int a, int r, int g, int b) {
26 | return Color.parseColor(colorDecToHexString(a, r, g, b));
27 | }
28 |
29 | public static String colorDecToHexString(int r, int g, int b) {
30 | return colorDecToHexString(255,r,g,b);
31 | }
32 |
33 | public static String colorDecToHexString(int a, int r, int g, int b) {
34 | String red = Integer.toHexString(r);
35 | String green = Integer.toHexString(g);
36 | String blue = Integer.toHexString(b);
37 | String alpha = Integer.toHexString(a);
38 |
39 | if (red.length() == 1) {
40 | red = "0" + red;
41 | }
42 | if (green.length() == 1) {
43 | green = "0" + green;
44 | }
45 | if (blue.length() == 1) {
46 | blue = "0" + blue;
47 | }
48 | if (alpha.length() == 1){
49 | alpha = "0" + alpha;
50 | }
51 |
52 | return "#" + alpha + red + green + blue;
53 | }
54 |
55 | public static int adjustAlpha(@ColorInt int color, float factor) {
56 | int alpha = Math.round(Color.alpha(color) * factor);
57 | int red = Color.red(color);
58 | int green = Color.green(color);
59 | int blue = Color.blue(color);
60 | return Color.argb(alpha, red, green, blue);
61 | }
62 |
63 | public static void adjustAlpha(SoulColor color, float factor) {
64 | color.setAlpha(Math.round(color.getAlpha() * factor));
65 | }
66 |
67 | public static void interpolateColor(SoulColor start, SoulColor end, float amount, SoulColor result) {
68 | result.setColor(start);
69 |
70 | result.setRed((int)(start.red + ((end.red - start.red) * amount)));
71 | result.setGreen((int)(start.green + ((end.green - start.green) * amount)));
72 | result.setBlue((int)(start.blue + ((end.blue - start.blue) * amount)));
73 | }
74 |
75 | public static SoulColor toSoulColor(int color){
76 | int alpha = Color.alpha(color);
77 | int red = Color.red(color);
78 | int green = Color.green(color);
79 | int blue = Color.blue(color);
80 | return new SoulColor(alpha, red, green, blue);
81 | }
82 |
83 | public static class SoulColor{
84 |
85 | private int tempColor;
86 |
87 | private int red;
88 | private int green;
89 | private int blue;
90 | private int alpha;
91 |
92 | public SoulColor(int alpha, int red, int green, int blue) {
93 | this.alpha = alpha;
94 | this.red = red;
95 | this.green = green;
96 | this.blue = blue;
97 | }
98 |
99 | public SoulColor(int red, int green, int blue) {
100 | this(1,red,green,blue);
101 | }
102 |
103 | public SoulColor(int color){
104 | this.alpha = Color.alpha(color);
105 | this.red = Color.red(color);
106 | this.green = Color.green(color);
107 | this.blue = Color.blue(color);
108 | }
109 |
110 | public SoulColor(){
111 | this(0x000000);
112 | }
113 |
114 | public void setColor(SoulColor color){
115 | this.alpha = color.alpha;
116 | this.red = color.red;
117 | this.green = color.green;
118 | this.blue = color.blue;
119 | }
120 |
121 | public void setColor(int color){
122 | this.alpha = Color.alpha(color);
123 | this.red = Color.red(color);
124 | this.green = Color.green(color);
125 | this.blue = Color.blue(color);
126 | }
127 |
128 | public int getRed() {
129 | return red;
130 | }
131 |
132 | public void setRed(int red) {
133 | this.red = red;
134 | }
135 |
136 | public int getGreen() {
137 | return green;
138 | }
139 |
140 | public void setGreen(int green) {
141 | this.green = green;
142 | }
143 |
144 | public int getBlue() {
145 | return blue;
146 | }
147 |
148 | public void setBlue(int blue) {
149 | this.blue = blue;
150 | }
151 |
152 | public int getAlpha() {
153 | return alpha;
154 | }
155 |
156 | public void setAlpha(int alpha) {
157 | this.alpha = alpha;
158 | }
159 |
160 | public void setAlpha(float alpha) {
161 | this.alpha = Math.round(255f * alpha);
162 | }
163 |
164 | public int toColor(){
165 | if(tempColor == -1){
166 | tempColor = Color.argb(alpha,red,green,blue);
167 | return tempColor;
168 | }else{
169 | if(colorChanged()){
170 | tempColor = Color.argb(alpha,red,green,blue);
171 | return tempColor;
172 | }
173 | }
174 |
175 | return tempColor;
176 | }
177 |
178 | private boolean colorChanged(){
179 | return true;
180 | }
181 |
182 | public static SoulColor copy(SoulColor color){
183 | return new SoulColor(color.alpha,color.red,color.green,color.blue);
184 | }
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/indicatoreffectlib/src/main/java/com/eudycontreras/indicatoreffectlib/utilities/DimensionUtility.java:
--------------------------------------------------------------------------------
1 | package com.eudycontreras.indicatoreffectlib.utilities;
2 |
3 | import android.content.Context;
4 | import android.content.res.Resources;
5 | import android.util.DisplayMetrics;
6 | import androidx.annotation.RestrictTo;
7 |
8 | /**
9 | * Note: Unlicensed private property of the author and creator
10 | * unauthorized use of this class outside of the Indicator Effect project
11 | * by the author may result on legal prosecution.
12 | *
13 | * Created by Eudy Contreras
14 | *
15 | * @author Eudy Contreras
16 | * @version 1.0
17 | * @since 2018-03-31
18 | */
19 | @RestrictTo(RestrictTo.Scope.LIBRARY)
20 | public class DimensionUtility {
21 |
22 | /**
23 | * This method converts dp unit to equivalent pixels, depending on device density.
24 | *
25 | * @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
26 | * @param context Context to get resources and device specific display metrics
27 | * @return A float value to represent px equivalent to dp depending on device density
28 | */
29 | public static float convertDpToPixel(Context context, float dp){
30 | Resources resources = context.getResources();
31 | DisplayMetrics metrics = resources.getDisplayMetrics();
32 | float px = dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
33 | return px;
34 | }
35 |
36 | /**
37 | * This method converts device specific pixels to density independent pixels.
38 | *
39 | * @param px A value in px (pixels) unit. Which we need to convert into db
40 | * @param context Context to get resources and device specific display metrics
41 | * @return A float value to represent dp equivalent to px value
42 | */
43 | public static float convertPixelsToDp(Context context, float px){
44 | Resources resources = context.getResources();
45 | DisplayMetrics metrics = resources.getDisplayMetrics();
46 | float dp = px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
47 | return dp;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/indicatoreffectlib/src/main/java/com/eudycontreras/indicatoreffectlib/views/IndicatorView.java:
--------------------------------------------------------------------------------
1 | package com.eudycontreras.indicatoreffectlib.views;
2 |
3 | import android.animation.*;
4 | import android.annotation.TargetApi;
5 | import android.content.Context;
6 | import android.content.res.TypedArray;
7 | import android.graphics.Canvas;
8 | import android.graphics.Color;
9 | import android.graphics.Paint;
10 | import android.os.Build;
11 | import android.util.AttributeSet;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.view.ViewParent;
15 | import android.view.animation.DecelerateInterpolator;
16 | import android.view.animation.Interpolator;
17 | import android.view.animation.LinearInterpolator;
18 | import androidx.annotation.NonNull;
19 | import com.eudycontreras.indicatoreffectlib.Bounds;
20 | import com.eudycontreras.indicatoreffectlib.Property;
21 | import com.eudycontreras.indicatoreffectlib.R;
22 | import com.eudycontreras.indicatoreffectlib.particles.ParticleIndicator;
23 | import com.eudycontreras.indicatoreffectlib.utilities.ColorUtility;
24 | import com.eudycontreras.indicatoreffectlib.utilities.DimensionUtility;
25 |
26 | import java.util.ArrayList;
27 |
28 | /**
29 | * Note: Unlicensed private property of the author and creator
30 | * unauthorized use of this class outside of the Indicator Effect project
31 | * by the author may result on legal prosecution.
32 | *
33 | * Created by Eudy Contreras
34 | *
35 | * @author Eudy Contreras
36 | * @version 1.0
37 | * @since 2018-03-31
38 | */
39 | public class IndicatorView extends View {
40 |
41 | @FunctionalInterface
42 | public interface IndicatorLayoutBehaviour {
43 | void setUpBehaviour(View view, int wrappedWidth, int wrappedHeight);
44 | }
45 |
46 | public static final int INDICATOR_SHAPE_CIRCLE = 0;
47 | public static final int INDICATOR_SHAPE_RECTANGLE = 1;
48 |
49 | public static final int INDICATOR_TYPE_OUTLINE = 0;
50 | public static final int INDICATOR_TYPE_FILLED = 1;
51 | public static final int INDICATOR_TYPE_AROUND = 2;
52 |
53 | public static final int INFINITE_REPEATS = ObjectAnimator.INFINITE;
54 |
55 | public static final int REPEAT_MODE_RESTART = ObjectAnimator.RESTART;
56 | public static final int REPEAT_MODE_REVERSE = ObjectAnimator.REVERSE;
57 |
58 | private int backgroundColor = Color.TRANSPARENT;
59 |
60 | private int indicatorShape = INDICATOR_SHAPE_CIRCLE;
61 | private int indicatorType;
62 | private int indicatorCount;
63 | private int indicatorColor;
64 | private int indicatorStrokeColor;
65 | private int indicatorColorStart;
66 | private int indicatorColorEnd;
67 | private int indicatorRepeats;
68 | private int indicatorRepeatMode;
69 | private int indicatorInnerOutlineColor;
70 |
71 | private int usableWidth;
72 | private int usableHeight;
73 |
74 | private float indicatorX = Integer.MIN_VALUE;
75 | private float indicatorY = Integer.MIN_VALUE;
76 |
77 | private float centerX = Integer.MIN_VALUE;
78 | private float centerY = Integer.MIN_VALUE;
79 |
80 | private float offsetX = 0f;
81 | private float offsetY = 0f;
82 |
83 | private float innerOutLineWidth;
84 |
85 | private float indicatorMinWidth;
86 | private float indicatorMinHeight;
87 |
88 | private float indicatorMaxWidth;
89 | private float indicatorMaxHeight;
90 |
91 | private float indicatorMinOpacity;
92 | private float indicatorMaxOpacity;
93 |
94 | private float indicatorClipRadius;
95 | private float indicatorMaxRadius;
96 | private float indicatorMinRadius;
97 |
98 | private float indicatorCornerRadius;
99 |
100 | private float indicatorStrokeWidth;
101 |
102 | private long revealDuration = 0;
103 | private long concealDuration = 0;
104 | private long indicatorDelay;
105 | private long indicatorDuration;
106 | private long indicatorIntervalDelay;
107 |
108 | private boolean showInnerOutline = false;
109 | private boolean useColorInterpolation = false;
110 | private boolean showBorderStroke = false;
111 | private boolean animationRunning = false;
112 | private boolean autoStartIndicator = false;
113 | private boolean cleanUpAfter = false;
114 |
115 | private ParticleIndicator[] indicators;
116 | private ArrayList