/
BallView.java
149 lines (130 loc) · 4.51 KB
/
BallView.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package com.github.glomadrian.loadingballs;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.View;
import com.github.glomadrian.loadingballs.animator.AbstractBallAnimator;
import com.github.glomadrian.loadingballs.animator.BallPathAnimator;
import com.github.glomadrian.loadingballs.animator.BallSizeAnimator;
import com.github.glomadrian.loadingballs.factory.PathFactory;
import java.util.ArrayList;
import java.util.List;
/**
* @author Adrián García Lomas
*/
public class BallView extends View {
private List<Ball> balls;
private float minBallSize;
private float maxBallSize;
private float ballSize = 20;
private BallPathAnimator ballPathAnimator;
private BallSizeAnimator ballSizeAnimator;
private int numberOfBalls = 3;
private int ballSizeAnimationDuration = 400;
private int ballPathAnimationDuration = 1500;
private boolean sizeAnimationEnabled = false;
private int[] ballColors;
private String pathType;
public BallView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public BallView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
defaultBallColors();
initAttributes(attrs);
createBalls();
}
private void defaultBallColors() {
ballColors = new int[] { -9956, -46262, -12742913 };
}
private void initAttributes(AttributeSet attrs) {
TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.LoadingBalls);
numberOfBalls = attributes.getInt(R.styleable.LoadingBalls_balls, numberOfBalls);
ballSize = attributes.getDimension(R.styleable.LoadingBalls_ball_size, ballSize);
minBallSize = attributes.getDimension(R.styleable.LoadingBalls_min_ball_size, ballSize / 2);
maxBallSize = attributes.getDimension(R.styleable.LoadingBalls_max_ball_size, ballSize * 2);
ballSizeAnimationDuration =
attributes.getInt(R.styleable.LoadingBalls_size_cycle_time, ballSizeAnimationDuration);
ballPathAnimationDuration =
attributes.getInt(R.styleable.LoadingBalls_movement_cycle_time, ballPathAnimationDuration);
sizeAnimationEnabled =
attributes.getBoolean(R.styleable.LoadingBalls_enable_size_animation, false);
initColorsAttributes(attributes);
pathType = attributes.getString(R.styleable.LoadingBalls_path);
if (pathType == null) {
pathType = PathFactory.INFINITE;
}
}
private void initColorsAttributes(TypedArray attributes) {
int arrayResourceId = attributes.getResourceId(R.styleable.LoadingBalls_ball_colors, 0);
if (arrayResourceId != 0) {
ballColors = getResources().getIntArray(arrayResourceId);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Path path = PathFactory.makePath(pathType, new Point(w / 2, h / 2), w, h, (int) maxBallSize);
initBallPathAnimator(path);
if (sizeAnimationEnabled) {
initBallSizeAnimator(path);
}
start();
}
private void initBallPathAnimator(Path path) {
ballPathAnimator = new BallPathAnimator(path, ballPathAnimationDuration);
ballPathAnimator.setBallPathAnimatorListener(new AnimatorListener());
ballPathAnimator.addBalls(balls);
}
private void initBallSizeAnimator(Path path) {
ballSizeAnimator =
new BallSizeAnimator(path, ballSizeAnimationDuration, minBallSize, maxBallSize);
ballSizeAnimator.addBalls(balls);
}
private void createBalls() {
balls = new ArrayList<>();
for (int i = 0, k = 0; i < numberOfBalls; i++, k++) {
if (!(ballColors.length - 1 >= k)) {
k = 0;
}
balls.add(new Ball(ballSize, ballColors[k]));
}
}
public void start() {
ballPathAnimator.start();
if (sizeAnimationEnabled) {
ballSizeAnimator.start();
}
}
public void stop() {
ballPathAnimator.stop();
if (sizeAnimationEnabled) {
ballSizeAnimator.start();
}
}
public void restart() {
ballPathAnimator.restart();
if (sizeAnimationEnabled) {
ballSizeAnimator.restart();
}
}
@Override
protected void onDraw(Canvas canvas) {
for (Ball ball : balls) {
ball.render(canvas);
}
}
private class AnimatorListener implements AbstractBallAnimator.BallAnimatorListener {
@Override
public void onUpdate() {
invalidate();
}
}
}