float
. This type-specific subclass enables performance benefit by allowing
23 | * calls to a {@link #set(Object, Float) set()} function that takes the primitive
24 | * float
type and avoids autoboxing and other overhead associated with the
25 | * Float
class.
26 | *
27 | * @param float
.
38 | */
39 | public abstract void setValue(T object, float value);
40 |
41 | @Override
42 | final public void set(T object, Float value) {
43 | setValue(object, value);
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/animation/IntProperty.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.ybq.android.spinkit.animation;
17 |
18 | import android.util.Property;
19 |
20 | /**
21 | * An implementation of {@link android.util.Property} to be used specifically with fields of type
22 | * int
. This type-specific subclass enables performance benefit by allowing
23 | * calls to a {@link #set(Object, Integer) set()} function that takes the primitive
24 | * int
type and avoids autoboxing and other overhead associated with the
25 | * Integer
class.
26 | *
27 | * @param int
.
38 | */
39 | public abstract void setValue(T object, int value);
40 |
41 | @Override
42 | final public void set(T object, Integer value) {
43 | setValue(object, value);
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/animation/SpriteAnimatorBuilder.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.animation;
2 |
3 | import android.animation.Keyframe;
4 | import android.animation.ObjectAnimator;
5 | import android.animation.PropertyValuesHolder;
6 | import android.util.Log;
7 | import android.util.Property;
8 | import android.view.animation.Animation;
9 | import android.view.animation.Interpolator;
10 |
11 | import com.github.ybq.android.spinkit.animation.interpolator.KeyFrameInterpolator;
12 | import com.github.ybq.android.spinkit.sprite.Sprite;
13 |
14 | import java.util.HashMap;
15 | import java.util.Locale;
16 | import java.util.Map;
17 |
18 | /**
19 | * Created by ybq.
20 | */
21 | public class SpriteAnimatorBuilder {
22 |
23 | private static final String TAG = "SpriteAnimatorBuilder";
24 | private Sprite sprite;
25 | private Interpolator interpolator;
26 | private int repeatCount = Animation.INFINITE;
27 | private long duration = 2000;
28 | private int startFrame = 0;
29 | private Map
40 | * The {@link Path} must not have gaps in the x direction and must not
41 | * loop back on itself such that there can be two points sharing the same x coordinate.
42 | *
43 | * @param path the {@link Path} to use to make the line representing the {@link Interpolator}
44 | * @return the {@link Interpolator} representing the {@link Path}
45 | */
46 | @SuppressWarnings("unused")
47 | public static Interpolator create(Path path) {
48 | if (Build.VERSION.SDK_INT >= 21) {
49 | return PathInterpolatorCompatApi21.create(path);
50 | }
51 | return PathInterpolatorCompatBase.create(path);
52 | }
53 |
54 | /**
55 | * Create an {@link Interpolator} for a quadratic Bezier curve. The end points
56 | * {@code (0, 0)} and {@code (1, 1)} are assumed.
57 | *
58 | * @param controlX the x coordinate of the quadratic Bezier control point
59 | * @param controlY the y coordinate of the quadratic Bezier control point
60 | * @return the {@link Interpolator} representing the quadratic Bezier curve
61 | */
62 | @SuppressWarnings("unused")
63 | public static Interpolator create(float controlX, float controlY) {
64 | if (Build.VERSION.SDK_INT >= 21) {
65 | return PathInterpolatorCompatApi21.create(controlX, controlY);
66 | }
67 | return PathInterpolatorCompatBase.create(controlX, controlY);
68 | }
69 |
70 | /**
71 | * Create an {@link Interpolator} for a cubic Bezier curve. The end points
72 | * {@code (0, 0)} and {@code (1, 1)} are assumed.
73 | *
74 | * @param controlX1 the x coordinate of the first control point of the cubic Bezier
75 | * @param controlY1 the y coordinate of the first control point of the cubic Bezier
76 | * @param controlX2 the x coordinate of the second control point of the cubic Bezier
77 | * @param controlY2 the y coordinate of the second control point of the cubic Bezier
78 | * @return the {@link Interpolator} representing the cubic Bezier curve
79 | */
80 | public static Interpolator create(float controlX1, float controlY1,
81 | float controlX2, float controlY2) {
82 | if (Build.VERSION.SDK_INT >= 21) {
83 | return PathInterpolatorCompatApi21.create(controlX1, controlY1, controlX2, controlY2);
84 | }
85 | return PathInterpolatorCompatBase.create(controlX1, controlY1, controlX2, controlY2);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorCompatApi21.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.ybq.android.spinkit.animation.interpolator;
18 |
19 | import android.annotation.TargetApi;
20 | import android.graphics.Path;
21 | import android.os.Build;
22 | import android.view.animation.Interpolator;
23 | import android.view.animation.PathInterpolator;
24 |
25 | /**
26 | * API 21+ implementation for path interpolator compatibility.
27 | */
28 | class PathInterpolatorCompatApi21 {
29 |
30 | private PathInterpolatorCompatApi21() {
31 | // prevent instantiation
32 | }
33 |
34 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
35 | public static Interpolator create(Path path) {
36 | return new PathInterpolator(path);
37 | }
38 |
39 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
40 | public static Interpolator create(float controlX, float controlY) {
41 | return new PathInterpolator(controlX, controlY);
42 | }
43 |
44 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
45 | public static Interpolator create(float controlX1, float controlY1,
46 | float controlX2, float controlY2) {
47 | return new PathInterpolator(controlX1, controlY1, controlX2, controlY2);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorCompatBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.github.ybq.android.spinkit.animation.interpolator;
18 |
19 | import android.graphics.Path;
20 | import android.view.animation.Interpolator;
21 |
22 | /**
23 | * Base implementation for path interpolator compatibility.
24 | */
25 | class PathInterpolatorCompatBase {
26 |
27 | private PathInterpolatorCompatBase() {
28 | // prevent instantiation
29 | }
30 |
31 | public static Interpolator create(Path path) {
32 | return new PathInterpolatorDonut(path);
33 | }
34 |
35 | public static Interpolator create(float controlX, float controlY) {
36 | return new PathInterpolatorDonut(controlX, controlY);
37 | }
38 |
39 | public static Interpolator create(float controlX1, float controlY1,
40 | float controlX2, float controlY2) {
41 | return new PathInterpolatorDonut(controlX1, controlY1, controlX2, controlY2);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/animation/interpolator/PathInterpolatorDonut.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.github.ybq.android.spinkit.animation.interpolator;
17 |
18 | import android.graphics.Path;
19 | import android.graphics.PathMeasure;
20 | import android.view.animation.Interpolator;
21 |
22 | /**
23 | * A path interpolator implementation compatible with API 4+.
24 | */
25 | class PathInterpolatorDonut implements Interpolator {
26 |
27 | /**
28 | * Governs the accuracy of the approximation of the {@link Path}.
29 | */
30 | private static final float PRECISION = 0.002f;
31 |
32 | private final float[] mX;
33 | private final float[] mY;
34 |
35 | public PathInterpolatorDonut(Path path) {
36 | final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);
37 |
38 | final float pathLength = pathMeasure.getLength();
39 | final int numPoints = (int) (pathLength / PRECISION) + 1;
40 |
41 | mX = new float[numPoints];
42 | mY = new float[numPoints];
43 |
44 | final float[] position = new float[2];
45 | for (int i = 0; i < numPoints; ++i) {
46 | final float distance = (i * pathLength) / (numPoints - 1);
47 | pathMeasure.getPosTan(distance, position, null /* tangent */);
48 |
49 | mX[i] = position[0];
50 | mY[i] = position[1];
51 | }
52 | }
53 |
54 | public PathInterpolatorDonut(float controlX, float controlY) {
55 | this(createQuad(controlX, controlY));
56 | }
57 |
58 | public PathInterpolatorDonut(float controlX1, float controlY1,
59 | float controlX2, float controlY2) {
60 | this(createCubic(controlX1, controlY1, controlX2, controlY2));
61 | }
62 |
63 | @Override
64 | public float getInterpolation(float t) {
65 | if (t <= 0.0f) {
66 | return 0.0f;
67 | } else if (t >= 1.0f) {
68 | return 1.0f;
69 | }
70 |
71 | // Do a binary search for the correct x to interpolate between.
72 | int startIndex = 0;
73 | int endIndex = mX.length - 1;
74 | while (endIndex - startIndex > 1) {
75 | int midIndex = (startIndex + endIndex) / 2;
76 | if (t < mX[midIndex]) {
77 | endIndex = midIndex;
78 | } else {
79 | startIndex = midIndex;
80 | }
81 | }
82 |
83 | final float xRange = mX[endIndex] - mX[startIndex];
84 | if (xRange == 0) {
85 | return mY[startIndex];
86 | }
87 |
88 | final float tInRange = t - mX[startIndex];
89 | final float fraction = tInRange / xRange;
90 |
91 | final float startY = mY[startIndex];
92 | final float endY = mY[endIndex];
93 |
94 | return startY + (fraction * (endY - startY));
95 | }
96 |
97 | private static Path createQuad(float controlX, float controlY) {
98 | final Path path = new Path();
99 | path.moveTo(0.0f, 0.0f);
100 | path.quadTo(controlX, controlY, 1.0f, 1.0f);
101 | return path;
102 | }
103 |
104 | private static Path createCubic(float controlX1, float controlY1,
105 | float controlX2, float controlY2) {
106 | final Path path = new Path();
107 | path.moveTo(0.0f, 0.0f);
108 | path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1.0f, 1.0f);
109 | return path;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/sprite/CircleLayoutContainer.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.sprite;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Rect;
5 |
6 | /**
7 | * Created by ybq.
8 | */
9 | public abstract class CircleLayoutContainer extends SpriteContainer {
10 |
11 | @Override
12 | public void drawChild(Canvas canvas) {
13 | for (int i = 0; i < getChildCount(); i++) {
14 | Sprite sprite = getChildAt(i);
15 | int count = canvas.save();
16 | canvas.rotate(i * 360 / getChildCount(),
17 | getBounds().centerX(),
18 | getBounds().centerY());
19 | sprite.draw(canvas);
20 | canvas.restoreToCount(count);
21 | }
22 | }
23 |
24 | @Override
25 | protected void onBoundsChange(Rect bounds) {
26 | super.onBoundsChange(bounds);
27 | bounds = clipSquare(bounds);
28 | int radius = (int) (bounds.width() * Math.PI / 3.6f / getChildCount());
29 | int left = bounds.centerX() - radius;
30 | int right = bounds.centerX() + radius;
31 | for (int i = 0; i < getChildCount(); i++) {
32 | Sprite sprite = getChildAt(i);
33 | sprite.setDrawBounds(left, bounds.top, right, bounds.top + radius * 2);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/sprite/CircleSprite.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.sprite;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 |
7 | /**
8 | * Created by ybq.
9 | */
10 | public class CircleSprite extends ShapeSprite {
11 |
12 | @Override
13 | public ValueAnimator onCreateAnimation() {
14 | return null;
15 | }
16 |
17 | @Override
18 | public void drawShape(Canvas canvas, Paint paint) {
19 | if (getDrawBounds() != null) {
20 | int radius = Math.min(getDrawBounds().width(), getDrawBounds().height()) / 2;
21 | canvas.drawCircle(getDrawBounds().centerX(),
22 | getDrawBounds().centerY(),
23 | radius, paint);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/sprite/RectSprite.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.sprite;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 |
7 | /**
8 | * Created by ybq.
9 | */
10 | public class RectSprite extends ShapeSprite {
11 | @Override
12 | public ValueAnimator onCreateAnimation() {
13 | return null;
14 | }
15 |
16 | @Override
17 | public void drawShape(Canvas canvas, Paint paint) {
18 | if (getDrawBounds() != null) {
19 | canvas.drawRect(getDrawBounds(), paint);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/sprite/RingSprite.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.sprite;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 |
7 | /**
8 | * Created by ybq.
9 | */
10 | public class RingSprite extends ShapeSprite {
11 |
12 |
13 | @Override
14 | public void drawShape(Canvas canvas, Paint paint) {
15 | if (getDrawBounds() != null) {
16 | paint.setStyle(Paint.Style.STROKE);
17 | int radius = Math.min(getDrawBounds().width(), getDrawBounds().height()) / 2;
18 | paint.setStrokeWidth(radius / 12);
19 | canvas.drawCircle(getDrawBounds().centerX(),
20 | getDrawBounds().centerY(),
21 | radius, paint);
22 | }
23 | }
24 |
25 | @Override
26 | public ValueAnimator onCreateAnimation() {
27 | return null;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/sprite/ShapeSprite.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.sprite;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.ColorFilter;
6 | import android.graphics.Paint;
7 |
8 | /**
9 | * Created by ybq.
10 | */
11 | public abstract class ShapeSprite extends Sprite {
12 |
13 | private Paint mPaint;
14 | private int mUseColor;
15 | private int mBaseColor;
16 |
17 | public ShapeSprite() {
18 | setColor(Color.WHITE);
19 | mPaint = new Paint();
20 | mPaint.setAntiAlias(true);
21 | mPaint.setColor(mUseColor);
22 | }
23 |
24 | @Override
25 | public void setColor(int color) {
26 | mBaseColor = color;
27 | updateUseColor();
28 | }
29 |
30 | @Override
31 | public int getColor() {
32 | return mBaseColor;
33 | }
34 |
35 | @SuppressWarnings("unused")
36 | public int getUseColor() {
37 | return mUseColor;
38 | }
39 |
40 | @Override
41 | public void setAlpha(int alpha) {
42 | super.setAlpha(alpha);
43 | updateUseColor();
44 | }
45 |
46 | private void updateUseColor() {
47 | int alpha = getAlpha();
48 | alpha += alpha >> 7;
49 | final int baseAlpha = mBaseColor >>> 24;
50 | final int useAlpha = baseAlpha * alpha >> 8;
51 | mUseColor = (mBaseColor << 8 >>> 8) | (useAlpha << 24);
52 | }
53 |
54 | @Override
55 | public void setColorFilter(ColorFilter colorFilter) {
56 | mPaint.setColorFilter(colorFilter);
57 | }
58 |
59 | @Override
60 | protected final void drawSelf(Canvas canvas) {
61 | mPaint.setColor(mUseColor);
62 | drawShape(canvas, mPaint);
63 | }
64 |
65 | public abstract void drawShape(Canvas canvas, Paint paint);
66 | }
67 |
--------------------------------------------------------------------------------
/library/src/main/java/com/github/ybq/android/spinkit/sprite/Sprite.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.spinkit.sprite;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.graphics.Camera;
5 | import android.graphics.Canvas;
6 | import android.graphics.ColorFilter;
7 | import android.graphics.Matrix;
8 | import android.graphics.PixelFormat;
9 | import android.graphics.Rect;
10 | import android.graphics.drawable.Animatable;
11 | import android.graphics.drawable.Drawable;
12 | import android.util.Property;
13 |
14 | import com.github.ybq.android.spinkit.animation.AnimationUtils;
15 | import com.github.ybq.android.spinkit.animation.FloatProperty;
16 | import com.github.ybq.android.spinkit.animation.IntProperty;
17 |
18 | /**
19 | * Created by ybq.
20 | */
21 | public abstract class Sprite extends Drawable implements
22 | ValueAnimator.AnimatorUpdateListener
23 | , Animatable
24 | , Drawable.Callback {
25 |
26 | private float scale = 1;
27 | private float scaleX = 1;
28 | private float scaleY = 1;
29 | private float pivotX;
30 | private float pivotY;
31 | private int animationDelay;
32 | private int rotateX;
33 | private int rotateY;
34 | private int translateX;
35 | private int translateY;
36 | private int rotate;
37 | private float translateXPercentage;
38 | private float translateYPercentage;
39 | private ValueAnimator animator;
40 | private int alpha = 255;
41 | private static final Rect ZERO_BOUNDS_RECT = new Rect();
42 | protected Rect drawBounds = ZERO_BOUNDS_RECT;
43 | private Camera mCamera;
44 | private Matrix mMatrix;
45 |
46 | public Sprite() {
47 | mCamera = new Camera();
48 | mMatrix = new Matrix();
49 | }
50 |
51 | public abstract int getColor();
52 |
53 | public abstract void setColor(int color);
54 |
55 | @Override
56 | public void setAlpha(int alpha) {
57 | this.alpha = alpha;
58 | }
59 |
60 | @Override
61 | public int getAlpha() {
62 | return alpha;
63 | }
64 |
65 | @Override
66 | public int getOpacity() {
67 | return PixelFormat.TRANSLUCENT;
68 | }
69 |
70 | public float getTranslateXPercentage() {
71 | return translateXPercentage;
72 | }
73 |
74 | public void setTranslateXPercentage(float translateXPercentage) {
75 | this.translateXPercentage = translateXPercentage;
76 | }
77 |
78 | public float getTranslateYPercentage() {
79 | return translateYPercentage;
80 | }
81 |
82 | public void setTranslateYPercentage(float translateYPercentage) {
83 | this.translateYPercentage = translateYPercentage;
84 | }
85 |
86 | public int getTranslateX() {
87 | return translateX;
88 | }
89 |
90 | public void setTranslateX(int translateX) {
91 | this.translateX = translateX;
92 | }
93 |
94 | public int getTranslateY() {
95 | return translateY;
96 | }
97 |
98 | public void setTranslateY(int translateY) {
99 | this.translateY = translateY;
100 | }
101 |
102 | public int getRotate() {
103 | return rotate;
104 | }
105 |
106 | public void setRotate(int rotate) {
107 | this.rotate = rotate;
108 | }
109 |
110 | public float getScale() {
111 | return scale;
112 | }
113 |
114 | public void setScale(float scale) {
115 | this.scale = scale;
116 | setScaleX(scale);
117 | setScaleY(scale);
118 | }
119 |
120 | public float getScaleX() {
121 | return scaleX;
122 | }
123 |
124 | public void setScaleX(float scaleX) {
125 | this.scaleX = scaleX;
126 | }
127 |
128 | public float getScaleY() {
129 | return scaleY;
130 | }
131 |
132 | public void setScaleY(float scaleY) {
133 | this.scaleY = scaleY;
134 | }
135 |
136 | public int getRotateX() {
137 | return rotateX;
138 | }
139 |
140 | public void setRotateX(int rotateX) {
141 | this.rotateX = rotateX;
142 | }
143 |
144 | public int getRotateY() {
145 | return rotateY;
146 | }
147 |
148 | public void setRotateY(int rotateY) {
149 | this.rotateY = rotateY;
150 | }
151 |
152 | public float getPivotX() {
153 | return pivotX;
154 | }
155 |
156 | public void setPivotX(float pivotX) {
157 | this.pivotX = pivotX;
158 | }
159 |
160 | public float getPivotY() {
161 | return pivotY;
162 | }
163 |
164 | public void setPivotY(float pivotY) {
165 | this.pivotY = pivotY;
166 | }
167 |
168 | @SuppressWarnings("unused")
169 | public int getAnimationDelay() {
170 | return animationDelay;
171 | }
172 |
173 | public Sprite setAnimationDelay(int animationDelay) {
174 | this.animationDelay = animationDelay;
175 | return this;
176 | }
177 |
178 | @Override
179 | public void setColorFilter(ColorFilter colorFilter) {
180 |
181 | }
182 |
183 | public abstract ValueAnimator onCreateAnimation();
184 |
185 | @Override
186 | public void start() {
187 | if (AnimationUtils.isStarted(animator)) {
188 | return;
189 | }
190 |
191 | animator = obtainAnimation();
192 | if (animator == null) {
193 | return;
194 | }
195 |
196 | AnimationUtils.start(animator);
197 | invalidateSelf();
198 | }
199 |
200 | public ValueAnimator obtainAnimation() {
201 | if (animator == null) {
202 | animator = onCreateAnimation();
203 | }
204 | if (animator != null) {
205 | animator.addUpdateListener(this);
206 | animator.setStartDelay(animationDelay);
207 | }
208 | return animator;
209 | }
210 |
211 | @Override
212 | public void stop() {
213 | if (AnimationUtils.isStarted(animator)) {
214 | animator.removeAllUpdateListeners();
215 | animator.end();
216 | reset();
217 | }
218 | }
219 |
220 | protected abstract void drawSelf(Canvas canvas);
221 |
222 | public void reset() {
223 | scale = 1;
224 | rotateX = 0;
225 | rotateY = 0;
226 | translateX = 0;
227 | translateY = 0;
228 | rotate = 0;
229 | translateXPercentage = 0f;
230 | translateYPercentage = 0f;
231 | }
232 |
233 | @Override
234 | public boolean isRunning() {
235 | return AnimationUtils.isRunning(animator);
236 | }
237 |
238 | @Override
239 | protected void onBoundsChange(Rect bounds) {
240 | super.onBoundsChange(bounds);
241 | setDrawBounds(bounds);
242 | }
243 |
244 | public void setDrawBounds(Rect drawBounds) {
245 | setDrawBounds(drawBounds.left, drawBounds.top, drawBounds.right, drawBounds.bottom);
246 | }
247 |
248 | public void setDrawBounds(int left, int top, int right, int bottom) {
249 | this.drawBounds = new Rect(left, top, right, bottom);
250 | setPivotX(getDrawBounds().centerX());
251 | setPivotY(getDrawBounds().centerY());
252 | }
253 |
254 | @Override
255 | public void invalidateDrawable(Drawable who) {
256 | invalidateSelf();
257 | }
258 |
259 | @Override
260 | public void scheduleDrawable(Drawable who, Runnable what, long when) {
261 |
262 | }
263 |
264 | @Override
265 | public void unscheduleDrawable(Drawable who, Runnable what) {
266 |
267 | }
268 |
269 | @Override
270 | public void onAnimationUpdate(ValueAnimator animation) {
271 | final Callback callback = getCallback();
272 | if (callback != null) {
273 | callback.invalidateDrawable(this);
274 | }
275 | }
276 |
277 | public Rect getDrawBounds() {
278 | return drawBounds;
279 | }
280 |
281 | @Override
282 | public void draw(Canvas canvas) {
283 | int tx = getTranslateX();
284 | tx = tx == 0 ? (int) (getBounds().width() * getTranslateXPercentage()) : tx;
285 | int ty = getTranslateY();
286 | ty = ty == 0 ? (int) (getBounds().height() * getTranslateYPercentage()) : ty;
287 | canvas.translate(tx, ty);
288 | canvas.scale(getScaleX(), getScaleY(), getPivotX(), getPivotY());
289 | canvas.rotate(getRotate(), getPivotX(), getPivotY());
290 |
291 | if (getRotateX() != 0 || getRotateY() != 0) {
292 | mCamera.save();
293 | mCamera.rotateX(getRotateX());
294 | mCamera.rotateY(getRotateY());
295 | mCamera.getMatrix(mMatrix);
296 | mMatrix.preTranslate(-getPivotX(), -getPivotY());
297 | mMatrix.postTranslate(getPivotX(), getPivotY());
298 | mCamera.restore();
299 | canvas.concat(mMatrix);
300 | }
301 | drawSelf(canvas);
302 | }
303 |
304 | public Rect clipSquare(Rect rect) {
305 | int w = rect.width();
306 | int h = rect.height();
307 | int min = Math.min(w, h);
308 | int cx = rect.centerX();
309 | int cy = rect.centerY();
310 | int r = min / 2;
311 | return new Rect(
312 | cx - r,
313 | cy - r,
314 | cx + r,
315 | cy + r
316 | );
317 | }
318 |
319 | public static final PropertyArgbEvaluator
that may be used in
31 | * {@link android.animation.ValueAnimator#setEvaluator(TypeEvaluator)}. The same instance may
32 | * be used in multiple Animator
s because it holds no state.
33 | *
34 | * @return An instance of ArgbEvalutor
.
35 | */
36 | public static ArgbEvaluator getInstance() {
37 | return sInstance;
38 | }
39 |
40 | /**
41 | * This function returns the calculated in-between value for a color
42 | * given integers that represent the start and end values in the four
43 | * bytes of the 32-bit int. Each channel is separately linearly interpolated
44 | * and the resulting calculated values are recombined into the return value.
45 | *
46 | * @param fraction The fraction from the starting to the ending values
47 | * @param startValue A 32-bit int value representing colors in the
48 | * separate bytes of the parameter
49 | * @param endValue A 32-bit int value representing colors in the
50 | * separate bytes of the parameter
51 | * @return A value that is calculated to be the linearly interpolated
52 | * result, derived by separating the start and end values into separate
53 | * color channels and interpolating each one separately, recombining the
54 | * resulting values in the same way.
55 | */
56 | public Object evaluate(float fraction, Object startValue, Object endValue) {
57 | int startInt = (Integer) startValue;
58 | int startA = (startInt >> 24) & 0xff;
59 | int startR = (startInt >> 16) & 0xff;
60 | int startG = (startInt >> 8) & 0xff;
61 | int startB = startInt & 0xff;
62 | int endInt = (Integer) endValue;
63 | int endA = (endInt >> 24) & 0xff;
64 | int endR = (endInt >> 16) & 0xff;
65 | int endG = (endInt >> 8) & 0xff;
66 | int endB = endInt & 0xff;
67 | return (startA + (int) (fraction * (endA - startA))) << 24 |
68 | (startR + (int) (fraction * (endR - startR))) << 16 |
69 | (startG + (int) (fraction * (endG - startG))) << 8 |
70 | (startB + (int) (fraction * (endB - startB)));
71 | }
72 | }
--------------------------------------------------------------------------------
/sample/src/main/java/com/github/ybq/android/loading/Colors.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.loading;
2 |
3 | /**
4 | * Created by ybq.
5 | */
6 | public interface Colors {
7 | int[] colors = new int[]{
8 | 0XFFD55400,
9 | 0XFF2B3E51,
10 | 0XFF00BD9C,
11 | 0XFF227FBB,
12 | 0XFF7F8C8D,
13 | 0XFFFFCC5C,
14 | 0XFFD55400,
15 | 0XFF1AAF5D,
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/github/ybq/android/loading/DetailActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.loading;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import com.github.ybq.android.spinkit.SpinKitView;
13 | import com.github.ybq.android.spinkit.SpriteFactory;
14 | import com.github.ybq.android.spinkit.Style;
15 | import com.github.ybq.android.spinkit.sprite.Sprite;
16 |
17 | import androidx.appcompat.app.AppCompatActivity;
18 | import androidx.viewpager.widget.PagerAdapter;
19 | import androidx.viewpager.widget.ViewPager;
20 |
21 | public class DetailActivity extends AppCompatActivity implements Colors {
22 |
23 | public static void start(Context context, int position) {
24 | Intent intent = new Intent(context, DetailActivity.class);
25 | intent.putExtra("position", position);
26 | context.startActivity(intent);
27 | }
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 | setContentView(R.layout.activity_detail);
33 | ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager);
34 | viewPager.setOffscreenPageLimit(0);
35 | viewPager.setAdapter(new PagerAdapter() {
36 | @Override
37 | public int getCount() {
38 | return Style.values().length;
39 | }
40 |
41 | @Override
42 | public boolean isViewFromObject(View view, Object object) {
43 | return view == object;
44 | }
45 |
46 | @Override
47 | public Object instantiateItem(ViewGroup container, int position) {
48 | @SuppressLint("InflateParams") View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_pager, null);
49 |
50 | SpinKitView spinKitView = (SpinKitView) view.findViewById(R.id.spin_kit);
51 | TextView name = (TextView) view.findViewById(R.id.name);
52 | Style style = Style.values()[position];
53 | name.setText(style.name().toLowerCase());
54 | Sprite drawable = SpriteFactory.create(style);
55 | spinKitView.setIndeterminateDrawable(drawable);
56 | container.addView(view);
57 |
58 | return view;
59 | }
60 |
61 | @Override
62 | public void destroyItem(ViewGroup container, int position, Object object) {
63 | container.removeView((View) object);
64 | }
65 | });
66 |
67 | viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
68 | @Override
69 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
70 | int color = (int) ArgbEvaluator.getInstance().evaluate(positionOffset,
71 | colors[position % colors.length],
72 | colors[(position + 1) % colors.length]);
73 | getWindow().getDecorView().setBackgroundColor(color);
74 | }
75 |
76 | @Override
77 | public void onPageSelected(int position) {
78 | getWindow().getDecorView().setBackgroundColor(colors[position % colors.length]);
79 | }
80 |
81 | @Override
82 | public void onPageScrollStateChanged(int state) {
83 |
84 | }
85 | });
86 |
87 | viewPager.setCurrentItem(getIntent().getIntExtra("position", 0));
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/github/ybq/android/loading/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.loading;
2 |
3 | import android.os.Bundle;
4 |
5 | import com.google.android.material.tabs.TabLayout;
6 |
7 | import androidx.appcompat.app.AppCompatActivity;
8 | import androidx.fragment.app.Fragment;
9 | import androidx.fragment.app.FragmentPagerAdapter;
10 | import androidx.viewpager.widget.ViewPager;
11 |
12 | public class MainActivity extends AppCompatActivity {
13 |
14 | TabLayout mTabLayout;
15 | ViewPager mViewPager;
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_main);
21 | mTabLayout = (TabLayout) findViewById(R.id.tabs);
22 | mViewPager = (ViewPager) findViewById(R.id.viewpager);
23 |
24 | mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {
25 |
26 | String[] titles = new String[]{
27 | "Style", "Widget"
28 | };
29 |
30 | @Override
31 | public Fragment getItem(int position) {
32 | if (position == 0) {
33 | return StyleFragment.newInstance();
34 | } else {
35 | return WidgetFragment.newInstance();
36 | }
37 | }
38 |
39 | @Override
40 | public int getCount() {
41 | return 2;
42 | }
43 |
44 | @Override
45 | public CharSequence getPageTitle(int position) {
46 | return titles[position];
47 | }
48 | });
49 | mTabLayout.setupWithViewPager(mViewPager);
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/github/ybq/android/loading/SquareFrameLayout.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.loading;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.util.AttributeSet;
7 | import android.widget.FrameLayout;
8 |
9 | /**
10 | * Created by ybq.
11 | */
12 | public class SquareFrameLayout extends FrameLayout {
13 | public SquareFrameLayout(Context context) {
14 | super(context);
15 | }
16 |
17 | public SquareFrameLayout(Context context, AttributeSet attrs) {
18 | super(context, attrs);
19 | }
20 |
21 | public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
22 | super(context, attrs, defStyleAttr);
23 | }
24 |
25 | @SuppressWarnings("unused")
26 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
27 | public SquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
28 | super(context, attrs, defStyleAttr, defStyleRes);
29 | }
30 |
31 | @Override
32 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
33 | //noinspection SuspiciousNameCombination
34 | super.onMeasure(widthMeasureSpec, widthMeasureSpec);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/github/ybq/android/loading/StyleFragment.java:
--------------------------------------------------------------------------------
1 | package com.github.ybq.android.loading;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import com.github.ybq.android.spinkit.SpinKitView;
10 | import com.github.ybq.android.spinkit.SpriteFactory;
11 | import com.github.ybq.android.spinkit.Style;
12 | import com.github.ybq.android.spinkit.sprite.Sprite;
13 |
14 | import androidx.annotation.Nullable;
15 | import androidx.fragment.app.Fragment;
16 | import androidx.recyclerview.widget.GridLayoutManager;
17 | import androidx.recyclerview.widget.RecyclerView;
18 |
19 | /**
20 | * Created by ybq.
21 | */
22 | public class StyleFragment extends Fragment implements Colors {
23 |
24 | public static StyleFragment newInstance() {
25 | return new StyleFragment();
26 | }
27 |
28 |
29 | @SuppressLint("InflateParams")
30 | @Nullable
31 | @Override
32 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
33 | return inflater.inflate(R.layout.fragment_style, null);
34 | }
35 |
36 | @Override
37 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
38 | super.onViewCreated(view, savedInstanceState);
39 | RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list);
40 | GridLayoutManager layoutManager = new GridLayoutManager(getContext(), 4);
41 | layoutManager.setOrientation(RecyclerView.VERTICAL);
42 | recyclerView.setLayoutManager(layoutManager);
43 |
44 | recyclerView.setAdapter(new RecyclerView.Adapter