Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 64c2a97

Browse files
author
dinuscxj
committed
complete CollisionLoadingRenderer's Builder
1 parent e2acc3e commit 64c2a97

File tree

6 files changed

+171
-98
lines changed

6 files changed

+171
-98
lines changed

app/src/main/java/app/dinus/com/example/CircleJumpActivity.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22

33
import android.content.Context;
44
import android.content.Intent;
5+
import android.graphics.Color;
56
import android.os.Bundle;
67
import android.support.v7.app.AppCompatActivity;
8+
import android.support.v7.widget.ViewUtils;
9+
10+
import app.dinus.com.loadingdrawable.DensityUtil;
11+
import app.dinus.com.loadingdrawable.LoadingView;
12+
import app.dinus.com.loadingdrawable.render.LoadingRenderer;
13+
import app.dinus.com.loadingdrawable.render.circle.jump.CollisionLoadingRenderer;
714

815
public class CircleJumpActivity extends AppCompatActivity {
916
public static void startActivity(Context context) {

library/src/main/java/app/dinus/com/loadingdrawable/render/circle/jump/CollisionLoadingRenderer.java

Lines changed: 154 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,9 @@
66
import android.graphics.ColorFilter;
77
import android.graphics.LinearGradient;
88
import android.graphics.Paint;
9-
import android.graphics.Rect;
109
import android.graphics.RectF;
1110
import android.graphics.Shader;
12-
import android.support.annotation.NonNull;
13-
import android.util.DisplayMetrics;
14-
import android.util.TypedValue;
11+
import android.support.annotation.Size;
1512
import android.view.animation.AccelerateInterpolator;
1613
import android.view.animation.DecelerateInterpolator;
1714
import android.view.animation.Interpolator;
@@ -23,21 +20,18 @@ public class CollisionLoadingRenderer extends LoadingRenderer {
2320
private static final Interpolator ACCELERATE_INTERPOLATOR = new AccelerateInterpolator();
2421
private static final Interpolator DECELERATE_INTERPOLATOR = new DecelerateInterpolator();
2522

26-
private static final int CIRCLE_COUNT = 7;
23+
private static final int DEFAULT_BALL_COUNT = 7;
2724

28-
//the 2 * 2 is the left and right side offset
29-
private static final float DEFAULT_WIDTH = 15.0f * (CIRCLE_COUNT + 2 * 2);
30-
//the 2 * 2 is the top and bottom side offset
31-
private static final float DEFAULT_HEIGHT = 15.0f * (1 + 2 * 2);
25+
private static final float DEFAULT_OVAL_HEIGHT = 1.5f;
26+
private static final float DEFAULT_BALL_RADIUS = 7.5f;
27+
private static final float DEFAULT_WIDTH = 15.0f * 11;
28+
private static final float DEFAULT_HEIGHT = 15.0f * 4;
3229

33-
private static final float DURATION_OFFSET = 0.25f;
3430
private static final float START_LEFT_DURATION_OFFSET = 0.25f;
3531
private static final float START_RIGHT_DURATION_OFFSET = 0.5f;
3632
private static final float END_RIGHT_DURATION_OFFSET = 0.75f;
3733
private static final float END_LEFT_DURATION_OFFSET = 1.0f;
3834

39-
private static final float DEFAULT_STROKE_WIDTH = 2.5f;
40-
4135
private static final int[] DEFAULT_COLORS = new int[]{
4236
Color.RED, Color.GREEN
4337
};
@@ -47,155 +41,240 @@ public class CollisionLoadingRenderer extends LoadingRenderer {
4741
};
4842

4943
private final Paint mPaint = new Paint();
50-
private final RectF mTempBounds = new RectF();
44+
private final RectF mOvalRect = new RectF();
5145

46+
@Size(2)
5247
private int[] mColors;
5348
private float[] mPositions;
5449

5550
private float mEndXOffsetProgress;
5651
private float mStartXOffsetProgress;
5752

58-
private float mStrokeWidth;
53+
private float mOvalVerticalRadius;
54+
55+
private float mBallRadius;
56+
private float mBallCenterY;
57+
private float mSideOffsets;
58+
private float mBallMoveXOffsets;
59+
private float mBallQuadCoefficient;
60+
61+
private int mBallCount;
5962

6063
private CollisionLoadingRenderer(Context context) {
6164
super(context);
6265
init(context);
66+
adjustParams();
6367
setupPaint();
6468
}
6569

6670
private void init(Context context) {
71+
mBallRadius = DensityUtil.dip2px(context, DEFAULT_BALL_RADIUS);
6772
mWidth = DensityUtil.dip2px(context, DEFAULT_WIDTH);
6873
mHeight = DensityUtil.dip2px(context, DEFAULT_HEIGHT);
69-
mStrokeWidth = DensityUtil.dip2px(context, DEFAULT_STROKE_WIDTH);
70-
}
74+
mOvalVerticalRadius = DensityUtil.dip2px(context, DEFAULT_OVAL_HEIGHT);
75+
76+
mBallCount = DEFAULT_BALL_COUNT;
7177

72-
private void setupPaint() {
7378
mColors = DEFAULT_COLORS;
7479
mPositions = DEFAULT_POSITIONS;
7580

76-
mPaint.setStrokeWidth(mStrokeWidth);
81+
//mBallMoveYOffsets = mBallQuadCoefficient * mBallMoveXOffsets ^ 2
82+
// ==> if mBallMoveYOffsets == mBallMoveXOffsets
83+
// ==> mBallQuadCoefficient = 1.0f / mBallMoveXOffsets;
84+
mBallMoveXOffsets = 1.5f * (2 * mBallRadius);
85+
mBallQuadCoefficient = 1.0f / mBallMoveXOffsets;
86+
}
87+
88+
private void adjustParams() {
89+
mBallCenterY = mHeight / 2.0f;
90+
mSideOffsets = (mWidth - mBallRadius * 2.0f * (mBallCount - 2)) / 2;
91+
}
92+
93+
private void setupPaint() {
7794
mPaint.setAntiAlias(true);
7895
mPaint.setStyle(Paint.Style.FILL);
96+
97+
mPaint.setShader(new LinearGradient(mSideOffsets, 0, mWidth - mSideOffsets, 0,
98+
mColors, mPositions, Shader.TileMode.CLAMP));
7999
}
80100

81101
@Override
82-
protected void draw(Canvas canvas, Rect bounds) {
102+
protected void draw(Canvas canvas) {
83103
int saveCount = canvas.save();
84104

85-
RectF arcBounds = mTempBounds;
86-
arcBounds.set(bounds);
87-
88-
float cy = mHeight / 2;
89-
float circleRadius = computeCircleRadius(arcBounds);
90-
91-
float sideOffset = 2.0f * (2 * circleRadius);
92-
float maxMoveOffset = 1.5f * (2 * circleRadius);
93-
94-
LinearGradient gradient = new LinearGradient(arcBounds.left + sideOffset, 0, arcBounds.right - sideOffset, 0,
95-
mColors, mPositions, Shader.TileMode.CLAMP);
96-
mPaint.setShader(gradient);
97-
98-
for (int i = 0; i < CIRCLE_COUNT; i++) {
105+
for (int i = 0; i < mBallCount; i++) {
106+
//yMoveOffset = mBallQuadCoefficient * xMoveOffset ^ 2
99107
if (i == 0 && mStartXOffsetProgress != 0) {
100-
float xMoveOffset = maxMoveOffset * mStartXOffsetProgress;
101-
// y = ax^2 --> if x = sideOffset, y = sideOffset ==> a = 1 / sideOffset
102-
float yMoveOffset = (float) (Math.pow(xMoveOffset, 2) / maxMoveOffset);
103-
canvas.drawCircle(circleRadius + sideOffset - xMoveOffset, cy - yMoveOffset, circleRadius, mPaint);
108+
float xMoveOffset = mBallMoveXOffsets * mStartXOffsetProgress;
109+
float yMoveOffset = (float) (Math.pow(xMoveOffset, 2) * mBallQuadCoefficient);
110+
canvas.drawCircle(mSideOffsets - mBallRadius - xMoveOffset, mBallCenterY - yMoveOffset, mBallRadius, mPaint);
111+
112+
float leftStartProgress = 1.0f - mStartXOffsetProgress;
113+
mOvalRect.set(mSideOffsets - mBallRadius - mBallRadius * leftStartProgress - xMoveOffset,
114+
mHeight - mOvalVerticalRadius - mOvalVerticalRadius * leftStartProgress,
115+
mSideOffsets - mBallRadius + mBallRadius * leftStartProgress - xMoveOffset,
116+
mHeight - mOvalVerticalRadius + mOvalVerticalRadius * leftStartProgress);
117+
canvas.drawOval(mOvalRect, mPaint);
104118
continue;
105119
}
106120

107-
if (i == CIRCLE_COUNT - 1 && mEndXOffsetProgress != 0) {
108-
float xMoveOffset = maxMoveOffset * mEndXOffsetProgress;
109-
// y = ax^2 --> if x = sideOffset, y = sideOffset / 2 ==> a = 1 / sideOffset
110-
float yMoveOffset = (float) (Math.pow(xMoveOffset, 2) / maxMoveOffset);
111-
canvas.drawCircle(circleRadius * (CIRCLE_COUNT * 2 - 1) + sideOffset + xMoveOffset, cy - yMoveOffset, circleRadius, mPaint);
121+
if (i == mBallCount - 1 && mEndXOffsetProgress != 0) {
122+
float xMoveOffset = mBallMoveXOffsets * mEndXOffsetProgress;
123+
float yMoveOffset = (float) (Math.pow(xMoveOffset, 2) * mBallQuadCoefficient);
124+
canvas.drawCircle(mBallRadius * (mBallCount * 2 - 3) + mSideOffsets + xMoveOffset, mBallCenterY - yMoveOffset, mBallRadius, mPaint);
125+
126+
float leftEndProgress = 1.0f - mEndXOffsetProgress;
127+
mOvalRect.set(mBallRadius * (mBallCount * 2 - 3) - mBallRadius * leftEndProgress + mSideOffsets + xMoveOffset,
128+
mHeight - mOvalVerticalRadius - mOvalVerticalRadius * leftEndProgress,
129+
mBallRadius * (mBallCount * 2 - 3) + mBallRadius * leftEndProgress + mSideOffsets + xMoveOffset,
130+
mHeight - mOvalVerticalRadius + mOvalVerticalRadius * leftEndProgress);
131+
canvas.drawOval(mOvalRect, mPaint);
112132
continue;
113133
}
114134

115-
canvas.drawCircle(circleRadius * (i * 2 + 1) + sideOffset, cy, circleRadius, mPaint);
135+
canvas.drawCircle(mBallRadius * (i * 2 - 1) + mSideOffsets, mBallCenterY, mBallRadius, mPaint);
136+
137+
mOvalRect.set(mBallRadius * (i * 2 - 2) + mSideOffsets, mHeight - mOvalVerticalRadius * 2,
138+
mBallRadius * (i * 2) + mSideOffsets, mHeight);
139+
canvas.drawOval(mOvalRect, mPaint);
116140
}
117141

118142
canvas.restoreToCount(saveCount);
119143
}
120144

121-
private float computeCircleRadius(RectF rectBounds) {
122-
float width = rectBounds.width();
123-
float height = rectBounds.height();
124-
125-
//CIRCLE_COUNT + 4 is the sliding distance of both sides
126-
float radius = Math.min(width / (CIRCLE_COUNT + 4) / 2, height / 2);
127-
return radius;
128-
}
129-
130145
@Override
131146
protected void computeRender(float renderProgress) {
132-
133-
// Moving the start offset to left only occurs in the first 25% of a
134-
// single ring animation
147+
// Moving the left ball to the left sides only occurs in the first 25% of a jump animation
135148
if (renderProgress <= START_LEFT_DURATION_OFFSET) {
136-
float startLeftOffsetProgress = renderProgress / DURATION_OFFSET;
149+
float startLeftOffsetProgress = renderProgress / START_LEFT_DURATION_OFFSET;
137150
mStartXOffsetProgress = DECELERATE_INTERPOLATOR.getInterpolation(startLeftOffsetProgress);
138-
139-
140151
return;
141152
}
142153

143-
// Moving the start offset to left only occurs between 25% and 50% of a
144-
// single ring animation
154+
// Moving the left ball to the origin location only occurs between 25% and 50% of a jump ring animation
145155
if (renderProgress <= START_RIGHT_DURATION_OFFSET) {
146-
float startRightOffsetProgress = (renderProgress - START_LEFT_DURATION_OFFSET) / DURATION_OFFSET;
156+
float startRightOffsetProgress = (renderProgress - START_LEFT_DURATION_OFFSET) / (START_RIGHT_DURATION_OFFSET - START_LEFT_DURATION_OFFSET);
147157
mStartXOffsetProgress = ACCELERATE_INTERPOLATOR.getInterpolation(1.0f - startRightOffsetProgress);
148-
149-
150158
return;
151159
}
152160

153-
// Moving the end offset to right starts between 50% and 75% a single ring
154-
// animation completes
161+
// Moving the right ball to the right sides only occurs between 50% and 75% of a jump animation
155162
if (renderProgress <= END_RIGHT_DURATION_OFFSET) {
156-
float endRightOffsetProgress = (renderProgress - START_RIGHT_DURATION_OFFSET) / DURATION_OFFSET;
163+
float endRightOffsetProgress = (renderProgress - START_RIGHT_DURATION_OFFSET) / (END_RIGHT_DURATION_OFFSET - START_RIGHT_DURATION_OFFSET);
157164
mEndXOffsetProgress = DECELERATE_INTERPOLATOR.getInterpolation(endRightOffsetProgress);
158-
159-
160165
return;
161166
}
162167

163-
// Moving the end offset to left starts after 75% of a single ring
164-
// animation completes
168+
// Moving the right ball to the origin location only occurs after 75% of a jump animation
165169
if (renderProgress <= END_LEFT_DURATION_OFFSET) {
166-
float endRightOffsetProgress = (renderProgress - END_RIGHT_DURATION_OFFSET) / DURATION_OFFSET;
170+
float endRightOffsetProgress = (renderProgress - END_RIGHT_DURATION_OFFSET) / (END_LEFT_DURATION_OFFSET - END_RIGHT_DURATION_OFFSET);
167171
mEndXOffsetProgress = ACCELERATE_INTERPOLATOR.getInterpolation(1 - endRightOffsetProgress);
168-
169-
170172
return;
171173
}
172174
}
173175

174176
@Override
175177
protected void setAlpha(int alpha) {
176178
mPaint.setAlpha(alpha);
177-
178179
}
179180

180181
@Override
181182
protected void setColorFilter(ColorFilter cf) {
182183
mPaint.setColorFilter(cf);
183-
184184
}
185185

186186
@Override
187187
protected void reset() {
188188
}
189189

190+
private void apply(Builder builder) {
191+
this.mWidth = builder.mWidth > 0 ? builder.mWidth : this.mWidth;
192+
this.mHeight = builder.mHeight > 0 ? builder.mHeight : this.mHeight;
193+
194+
this.mOvalVerticalRadius = builder.mOvalVerticalRadius > 0 ? builder.mOvalVerticalRadius : this.mOvalVerticalRadius;
195+
this.mBallRadius = builder.mBallRadius > 0 ? builder.mBallRadius : this.mBallRadius;
196+
this.mBallMoveXOffsets = builder.mBallMoveXOffsets > 0 ? builder.mBallMoveXOffsets : this.mBallMoveXOffsets;
197+
this.mBallQuadCoefficient = builder.mBallQuadCoefficient > 0 ? builder.mBallQuadCoefficient : this.mBallQuadCoefficient;
198+
this.mBallCount = builder.mBallCount > 0 ? builder.mBallCount : this.mBallCount;
199+
200+
this.mDuration = builder.mDuration > 0 ? builder.mDuration : this.mDuration;
201+
202+
this.mColors = builder.mColors != null ? builder.mColors : this.mColors;
203+
204+
adjustParams();
205+
setupPaint();
206+
}
207+
190208
public static class Builder {
191209
private Context mContext;
192210

211+
private int mWidth;
212+
private int mHeight;
213+
214+
private float mOvalVerticalRadius;
215+
216+
private int mBallCount;
217+
private float mBallRadius;
218+
private float mBallMoveXOffsets;
219+
private float mBallQuadCoefficient;
220+
221+
private int mDuration;
222+
223+
@Size(2)
224+
private int[] mColors;
225+
193226
public Builder(Context mContext) {
194227
this.mContext = mContext;
195228
}
196229

230+
public Builder setWidth(int width) {
231+
this.mWidth = width;
232+
return this;
233+
}
234+
235+
public Builder setHeight(int height) {
236+
this.mHeight = height;
237+
return this;
238+
}
239+
240+
public Builder setOvalVerticalRadius(int ovalVerticalRadius) {
241+
this.mOvalVerticalRadius = ovalVerticalRadius;
242+
return this;
243+
}
244+
245+
public Builder setBallRadius(float ballRadius) {
246+
this.mBallRadius = ballRadius;
247+
return this;
248+
}
249+
250+
public Builder setBallMoveXOffsets(float ballMoveXOffsets) {
251+
this.mBallMoveXOffsets = ballMoveXOffsets;
252+
return this;
253+
}
254+
255+
public Builder setBallQuadCoefficient(float ballQuadCoefficient) {
256+
this.mBallQuadCoefficient = ballQuadCoefficient;
257+
return this;
258+
}
259+
260+
public Builder setBallCount(int ballCount) {
261+
this.mBallCount = ballCount;
262+
return this;
263+
}
264+
265+
public Builder setColors(@Size(2) int[] colors) {
266+
this.mColors = colors;
267+
return this;
268+
}
269+
270+
public Builder setDuration(int duration) {
271+
this.mDuration = duration;
272+
return this;
273+
}
274+
197275
public CollisionLoadingRenderer build() {
198276
CollisionLoadingRenderer loadingRenderer = new CollisionLoadingRenderer(mContext);
277+
loadingRenderer.apply(this);
199278
return loadingRenderer;
200279
}
201280
}

library/src/main/java/app/dinus/com/loadingdrawable/render/circle/rotate/GearLoadingRenderer.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,29 +133,25 @@ protected void draw(Canvas canvas) {
133133

134134
@Override
135135
protected void computeRender(float renderProgress) {
136-
// Scaling up the start size only occurs in the first 20% of a
137-
// single ring animation
136+
// Scaling up the start size only occurs in the first 20% of a single ring animation
138137
if (renderProgress <= START_SCALE_DURATION_OFFSET) {
139138
float startScaleProgress = (renderProgress) / START_SCALE_DURATION_OFFSET;
140139
mScale = DECELERATE_INTERPOLATOR.getInterpolation(startScaleProgress);
141140
}
142141

143-
// Moving the start trim only occurs between 20% to 50% of a
144-
// single ring animation
142+
// Moving the start trim only occurs between 20% to 50% of a single ring animation
145143
if (renderProgress <= START_TRIM_DURATION_OFFSET && renderProgress > START_SCALE_DURATION_OFFSET) {
146144
float startTrimProgress = (renderProgress - START_SCALE_DURATION_OFFSET) / (START_TRIM_DURATION_OFFSET - START_SCALE_DURATION_OFFSET);
147145
mStartDegrees = mOriginStartDegrees + mGearSwipeDegrees * startTrimProgress;
148146
}
149147

150-
// Moving the end trim starts between 50% to 80% of a single ring
151-
// animation completes
148+
// Moving the end trim starts between 50% to 80% of a single ring animation
152149
if (renderProgress <= END_TRIM_DURATION_OFFSET && renderProgress > START_TRIM_DURATION_OFFSET) {
153150
float endTrimProgress = (renderProgress - START_TRIM_DURATION_OFFSET) / (END_TRIM_DURATION_OFFSET - START_TRIM_DURATION_OFFSET);
154151
mEndDegrees = mOriginEndDegrees + mGearSwipeDegrees * endTrimProgress;
155152
}
156153

157-
// Scaling down the end size starts after 80% of a single ring
158-
// animation completes
154+
// Scaling down the end size starts after 80% of a single ring animation
159155
if (renderProgress > END_TRIM_DURATION_OFFSET) {
160156
float endScaleProgress = (renderProgress - END_TRIM_DURATION_OFFSET) / (END_SCALE_DURATION_OFFSET - END_TRIM_DURATION_OFFSET);
161157
mScale = 1.0f - ACCELERATE_INTERPOLATOR.getInterpolation(endScaleProgress);

0 commit comments

Comments
 (0)