-
Notifications
You must be signed in to change notification settings - Fork 14
/
SplashView.java
286 lines (250 loc) · 9.39 KB
/
SplashView.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
package com.example.user.utils.weight.numal;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;
import com.example.user.utils.R;
/**
* com.wsq.study.widget
* 公司:浙江答分奇网络科技有限公司
* created by 吴世芊 on 2016/10/2 14:22.
* updated by
* 邮箱:apple9302@126.com
* 此类功能:
*/
public class SplashView extends View {
//大圆半径
private float mRotationRadius = 90;
//每个小圆的半径
private float mCircleRadius = 18;
//小圆圈的颜色列表
private int[] mCircleColors;
//大圆和小圆旋转的时间
private long mRotationDuration = 1200;
//第二部分动画的执行总时间(包括三个动画时间,各占1/3)
private long mSplashDuration = 1200;
//总体的背景颜色
private int mSplasBgColor = Color.WHITE;
/**
* 参数,保存了一些绘制状态,会被动态的改变
*/
//空心圆初始半径
private float mHoleRadius = 0F;
//当前大圆旋转的角度(弧度)
private float mCurrentRotationAngle = 0F;
//当前大圆的半径
private float mCurrentRotationRadius = mRotationRadius;
//画笔
private Paint mPaint = new Paint();
//绘制背景的画笔
private Paint mBackgroundPaint = new Paint();
//屏幕正中心的坐标
private float mCenterX, mCenterY;
//屏幕对角线一半
private float mDiagonalDist;
//保存当前动画状态---当前执行哪种动画
private SplashState mState = null;
private abstract class SplashState {
public abstract void drawState(Canvas canvas);
}
public SplashView(Context context) {
this(context, null);
}
public SplashView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SplashView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
//小圆颜色数组
mCircleColors = context.getResources().getIntArray(R.array.colors);
//画笔初始化
mPaint.setAntiAlias(true);
mBackgroundPaint.setAntiAlias(true);
//设置样式----边框样式---描边--颜色
mBackgroundPaint.setStyle(Paint.Style.STROKE);
mBackgroundPaint.setColor(mSplasBgColor);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//中心点
mCenterX = w / 2;
mCenterY = h / 2;
//对角线一半
mDiagonalDist = (float) (Math.sqrt(w * w + h * h) );
super.onSizeChanged(w, h, oldw, oldh);
}
//进入主界面,开启后面两个动画;
public void splashAndDisapear() {
if (mState!=null&&mState instanceof RotateState){
RotateState state= (RotateState) mState;
//取消旋转动画
state.cancle();
//进入下一个动画
post(new Runnable() {
@Override
public void run() {
mState=new MergingState();
}
});
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制小圆动画
if (mState == null) {
//第一次执行动画
mState = new RotateState();
}
mState.drawState(canvas);
}
//旋转动画
private class RotateState extends SplashState {
private ValueAnimator mAnimator;
public RotateState() {
//小圆的坐标--->大圆的半径,大圆旋转了多少角度
//属性动画--估值器 花了1200ms,计算某个时刻当前的角度是,0-2π之间的某个值
mAnimator = ValueAnimator.ofFloat(0, (float) Math.PI * 2);
//设置线性估值器----会平滑计算
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.setDuration(mRotationDuration);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//得到某个时间点的结果
//这个时间点,大圆旋转的而角度
mCurrentRotationAngle = (float) animation.getAnimatedValue();
//重绘---onDraw()
invalidate();
}
});
//设置旋转次数----不限次数
mAnimator.setRepeatCount(ValueAnimator.INFINITE);
//开始计算
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
//绘制小圆的旋转动画
//1.清空画板
drawBackground(canvas);
//2.绘制小圆
drawCircles(canvas);
}
public void cancle(){
mAnimator.cancel();
}
}
//聚合动画
private class MergingState extends SplashState {
private ValueAnimator mAnimator;
public MergingState() {
//动画-->估值器,1200ms 某个时刻大圆的半径
mAnimator = ValueAnimator.ofFloat(0, mRotationRadius);
//设置线性估值器----会平滑计算
mAnimator.setInterpolator(new OvershootInterpolator(10f));
mAnimator.setDuration(mSplashDuration/2);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//得到某个时间点的结果
//这个时间点,大圆的半径
mCurrentRotationRadius = (float) animation.getAnimatedValue();
//重绘---onDraw()
invalidate();
}
});
//监听动画执行完毕
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mState=new ExpandingState();
}
});
mAnimator.reverse();
//翻转后不能再调用start方法,否则就会恢复到原来的状态
// mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
//绘制小圆的旋转动画
//1.清空画板
drawBackground(canvas);
//2.绘制小圆
drawCircles(canvas);
}
}
//扩散动画,绘制空心圆
private class ExpandingState extends SplashState {
private ValueAnimator mAnimator;
public ExpandingState() {
//动画--估值器-->计算某个时刻空心圆的半径,0--到对角线的一半
mAnimator = ValueAnimator.ofFloat(0, mDiagonalDist/2);
//设置线性估值器----会平滑计算
// mAnimator.setInterpolator(new OvershootInterpolator(10f));
mAnimator.setDuration(mSplashDuration);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//得到某个时间点的结果
//这个时间点,大圆的半径
mHoleRadius = (float) animation.getAnimatedValue();
//重绘---onDraw()
invalidate();
}
});
// mAnimator.reverse();
//翻转后不能再调用start方法,否则就会恢复到原来的状态
mAnimator.start();
}
@Override
public void drawState(Canvas canvas) {
//绘制空心圆的扩散动画
drawBackground(canvas);
}
}
/**
* 清空画板
* @param canvas
*/
private void drawBackground(Canvas canvas) {
if (mHoleRadius>0f){
/**
* 绘制白色的空心圆
* 技巧:使用一个非常宽的画笔,不断减小画笔的的宽度
*/
//设置画笔的宽度=对角线/2-空心圆的半径
float strokeWidth=mDiagonalDist/2-mHoleRadius;
mBackgroundPaint.setStrokeWidth(strokeWidth);
float radius=mHoleRadius+strokeWidth/2;
canvas.drawCircle(mCenterX,mCenterY,radius,mBackgroundPaint);
}else {
canvas.drawColor(mSplasBgColor);
}
}
/**
* 绘制小圆
* @param canvas
*/
private void drawCircles(Canvas canvas) {
double rotationAngle=2*Math.PI/mCircleColors.length;
for (int i = 0; i <mCircleColors.length ;i++) {
double angle=i*rotationAngle+mCurrentRotationAngle;
mPaint.setColor(mCircleColors[i]);
float x= (float) (mCenterX+mCurrentRotationRadius*Math.cos( angle));
float y= (float) (mCenterY+mCurrentRotationRadius*Math.sin( angle));
canvas.drawCircle(x,y,mCircleRadius,mPaint);
}
}
}