自定义view————loading框

自定义view————loading框

写自定义view,怎么能没有自己写的loading框了,今天给大家送上一个loading框,前期losing框是很简单的效果,三个状态:loading、success、error,不逼逼了,先上给糙一点的效果GIF,回头继续完善。

效果图

糙一点的loading框效果看完了,接下来说一下实现过程,采用WindowManager将losing框的view置于显示view的上层,起初上来是loading转圈状态,根据加载返回的结构设置成功或者失败。

loading状态

ValueAnimator实现AnimatorUpdateListener、AnimatorListener监听方法,AnimatorUpdateListener中接受valueAnimator.getAnimatedValue();(不断回调的在0-1这个范围内,经过插值器插值之后的返回值),然后去画圈圈

这里画的是一个通过改变不同起始角度画给一个240度的圆弧,以此达到loading效果

1
2
3
4
5
mPath = new Path();
loadingrectF = new RectF(-100, -100, 100, 100);
mPath.addArc(loadingrectF, mAnimatorValue * 360, 240);
canvas.drawPath(mPath, mPaint);
canvas.drawColor(Color.parseColor("#33000000"));

mAnimatorValue值的变化是AnimatorUpdateListener函数里面回调的值,然后通知重绘

1
2
3
4
5
6
7
8
9
10
11
loadingvalueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// 不断回调的在0-1这个范围内,经过插值器插值之后的返回值
mAnimatorValue = (float) valueAnimator.getAnimatedValue();
//重绘
invalidate();
}
});

为了保证转了一圈过后继续转,这里引进Handler,在AnimatorListener的结束方法中进行通知动画继续

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
loadingvalueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
// getHandle发消息通知动画状态更新
mAnimatorHandler.sendEmptyMessage(0);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});

附上Handler相关代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
mAnimatorHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (mcurrentState) {
case LODING:
//保持loading时一直执行动画
loadingvalueAnimator.start();
break;
case SUCCES:
break;
case ERROR:
break;
default:
break;
}
}
};

到此为止,loading就能一直转了,接下来就是success、error两个状态了的讲解了

success状态

成功状态时,loading消失,显示成功的相关提醒(原谅我是一个程序员,做的loading不好看,准备后期功能完善后,会把loading、success、error状态的显示弄的像UI设计的一样),废话不多说了,该上菜了

1
2
3
4
5
6
7
8
9
10
/**
* 成功
*/
public void setSuccess() {
loadingvalueAnimator.removeAllListeners();
errorvalueAnimator.removeAllListeners();
addSuccesLoadingListener();
successvalueAnimator.start();
}

移除掉其他ValueAnimator对应的监听方法,为success加上ValueAnimator的监听方法,这里就是显示一下success状态的文案,保持500ms,然后显示(这一块可以改成其他动画酷炫效果)

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
successvalueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
//动画开始,去绘制success的文案
mcurrentState = State.SUCCES;
invalidate();
}
@Override
public void onAnimationEnd(Animator animator) {
//动画结束,隐藏状态
LoadingView.this.setVisibility(GONE);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});

error状态

和success状态同理,只是文案不一样

代码中使用

添加到activity开始loading动画,待结果返回时然后设置相关状态显示500ms,然后显示消失,接下来贴出模拟的loading—>success—>dismiss的一个过程

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
loadingRoundView = new LoadingView(this);
loadingRoundView.addPartentViewStartLoading(MainActivity.this);
mErrorHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (error <= 50) {
if (error == 0) {
loadingRoundView.startLoading();
}
error += 1;
mErrorHandler.sendEmptyMessageDelayed(0, 100);
} else {
loadingRoundView.setError();
}
}
};
//
mSuccesHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (succes <= 50) {
succes += 1;
mSuccesHandler.sendEmptyMessageDelayed(0, 100);
} else {
loadingRoundView.setSuccess();
mErrorHandler.sendEmptyMessageDelayed(0, 1000);
}
}
};
mSuccesHandler.sendEmptyMessageDelayed(0, 100);

设置loading方式

目前只写了三个loading方式

1
2
3
4
5
6
7
8
9
//loading的类型
private Type mcurrentType = Type.ROUND;
//loading type
public enum Type {
ARC,//传统弧形转圈
CIRCLE,//天女散花
ROUND,//渐变的圆圈旋转
}

然后根据不同的loading方法,ondraw()里面执行的方法也不一样

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
case LODING:
if (mcurrentType == Type.ARC) {
mPath = new Path();
RectF loadingrectF = new RectF(-radius, -radius, radius, radius);
mPath.addArc(loadingrectF, mAnimatorValue * 360, 240);
canvas.drawPath(mPath, mPaint);
} else if (mcurrentType == Type.CIRCLE) {
mPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
for (int i = 0; i < 10; i++) {
mPath.addCircle(mAnimatorValue * mwidth / 2 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 2 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 3 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 3 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 4 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 4 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 5 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 5 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 6 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 6 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
}
canvas.drawPath(mPath, mPaint);
} else if (mcurrentType == Type.ROUND) {
mPaint.setStyle(Paint.Style.FILL);
Path path = new Path();
path.addCircle(0, 0, radius, Path.Direction.CW); // 添加一个圆形
PathMeasure pathMeasure = new PathMeasure(path, false);
pathMeasure.getPosTan(pathMeasure.getLength() * mAnimatorValue, pos, tan);
// mPath = new Path();
//使用 Math.atan2(tan[1], tan[0]) 将 tan 转化为角(单位为弧度)的时候要注意参数顺序。
float angle = (float) Math.atan2(tan[1], tan[0]);
for (int i = 0; i < roundCount; i++) {
//用path一次性画的,透明度不好设置
// mPath.addCircle((float) (Math.cos(angle + i*0.4) * 100), (float) (Math.sin(angle+ i*0.4) * 100), 16, Path.Direction.CW);
mPaint.setAlpha(onealpha * i);
canvas.drawCircle((float) (Math.cos(angle + i * 0.4) * radius), (float) (Math.sin(angle + i * 0.4) * radius), circleRadius, mPaint);
}
// canvas.drawPath(mPath, circlePaint);
}
break;

附上loadingview完整代码

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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
package com.loadingview;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
/**
* Created by wujun on 2017/7/31.
*
* @author madreain
* @desc loading框 目前支持三种状态及三种样式
*/
public class LoadingView extends View {
//屏幕的宽高
int mwidth;
int mheight;
int backgroudColor;
//主
Paint mPaint;
//属性
int mpaintColor;
float mpaintStrokeWidth;
Path mPath;
//转圈的半径
float radius = 100;
//画圆圈的半径
float circleRadius = 16;
//设置转圈的圆点数量
private int roundCount = 10;
//1-255
private int onealpha;
private float[] pos; // 当前点的实际位置
private float[] tan; // 当前点的tangent值,用于计算图片所需旋转的角度
//loading的动效
ValueAnimator loadingvalueAnimator;
//loading 动画数值(用于控制动画状态,因为同一时间内只允许有一种状态出现,具体数值处理取决于当前状态)
private float mAnimatorValue = 0;
//loading 用于控制动画状态转换
private Handler mAnimatorHandler;
State mcurrentState = State.LODING;
//loading状态,loading,成功,失败
private enum State {
LODING,
SUCCES,
ERROR,
}
//成功失败的画笔
Paint textPaint;
int textPaintColor;
float textPaintStrokeWidth;
float textPaintTextSize;
//成功的动效
ValueAnimator successvalueAnimator;
//失败的动效
ValueAnimator errorvalueAnimator;
//loading的类型
private Type mcurrentType = Type.ROUND;
//loading type
public enum Type {
ARC,//传统弧形转圈
CIRCLE,//天女散花
ROUND,//渐变的圆圈旋转
}
public LoadingView(Context context) {
super(context);
initPaint();
initHandler();
initListener();
}
public LoadingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initTypedArray(context, attrs);
initPaint();
initHandler();
initListener();
}
private void initTypedArray(Context context, AttributeSet attrs) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LoadingView);
backgroudColor=typedArray.getColor(R.styleable.LoadingView_backgroudColor,Color.parseColor("#66000000"));
mpaintColor = typedArray.getColor(R.styleable.LoadingView_mpaintColor, Color.BLUE);
mpaintStrokeWidth = typedArray.getFloat(R.styleable.LoadingView_mpaintStrokeWidth, 16);
textPaintColor = typedArray.getColor(R.styleable.LoadingView_textPaintColor, Color.BLUE);
textPaintStrokeWidth = typedArray.getFloat(R.styleable.LoadingView_textPaintStrokeWidth, 6);
textPaintTextSize = typedArray.getFloat(R.styleable.LoadingView_textPaintTextSize, 60);
radius = typedArray.getFloat(R.styleable.LoadingView_radius, 100);
circleRadius = typedArray.getFloat(R.styleable.LoadingView_circleRadius, 16);
roundCount = typedArray.getInteger(R.styleable.LoadingView_roundCount, 10);
int type = typedArray.getInt(R.styleable.LoadingView_Type, 0);
if (type == 0) {
mcurrentType = Type.ARC;
} else if (type == 1) {
mcurrentType = Type.CIRCLE;
} else if (type == 2) {
mcurrentType = Type.ROUND;
}
}
public LoadingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initTypedArray(context, attrs);
initPaint();
initHandler();
initListener();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mwidth = w;
mheight = h;
}
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mpaintColor);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(mpaintStrokeWidth);
mPaint.setStyle(Paint.Style.STROKE);
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setColor(textPaintColor);
textPaint.setStrokeCap(Paint.Cap.ROUND);
textPaint.setStrokeWidth(textPaintStrokeWidth);
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setTextSize(textPaintTextSize);
pos = new float[2];
tan = new float[2];
//计算透明度
onealpha = 255 / roundCount;
}
private void initHandler() {
mAnimatorHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (mcurrentState) {
case LODING:
//保持loading时一直执行动画
loadingvalueAnimator.start();
break;
case SUCCES:
break;
case ERROR:
break;
default:
break;
}
}
};
}
private void initListener() {
// 创建0-1的一个过程,任何复杂的过程都可以采用归一化,然后在addUpdateListener回调里去做自己想要的变化
loadingvalueAnimator = ValueAnimator.ofFloat(0, 1);
// 设置过程的时间为2S
loadingvalueAnimator.setDuration(2000);
successvalueAnimator = ValueAnimator.ofFloat(0, 1);
successvalueAnimator.setDuration(500);
errorvalueAnimator = ValueAnimator.ofFloat(0, 1);
errorvalueAnimator.setDuration(500);
}
private void addLoadingListener() {
loadingvalueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
// 不断回调的在0-1这个范围内,经过插值器插值之后的返回值
mAnimatorValue = (float) valueAnimator.getAnimatedValue();
// 获取当前点坐标封装到mCurrentPosition
// mPathMeasure.getPosTan(mAnimatorValue, mCurrentPosition, null);
//重绘
invalidate();
}
});
loadingvalueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
// getHandle发消息通知动画状态更新
mAnimatorHandler.sendEmptyMessage(0);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
private void addSuccesLoadingListener() {
// successvalueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
// @Override
// public void onAnimationUpdate(ValueAnimator valueAnimator) {
//
//
// }
// });
successvalueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
mcurrentState = State.SUCCES;
invalidate();
}
@Override
public void onAnimationEnd(Animator animator) {
//动画结束,隐藏状态
LoadingView.this.setVisibility(GONE);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
private void addErrorLoadingListener() {
// errorvalueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
// @Override
// public void onAnimationUpdate(ValueAnimator valueAnimator) {
//
//
// }
// });
errorvalueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
mcurrentState = State.ERROR;
invalidate();
}
@Override
public void onAnimationEnd(Animator animator) {
//动画结束,隐藏状态
LoadingView.this.setVisibility(GONE);
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//移到屏幕中间
canvas.translate(mwidth / 2, mheight / 2);
//都添加背景
canvas.drawColor(backgroudColor);
drawLoading(canvas);
}
private void drawLoading(Canvas canvas) {
switch (mcurrentState) {
case LODING:
if (mcurrentType == Type.ARC) {
mPath = new Path();
RectF loadingrectF = new RectF(-radius, -radius, radius, radius);
mPath.addArc(loadingrectF, mAnimatorValue * 360, 240);
canvas.drawPath(mPath, mPaint);
} else if (mcurrentType == Type.CIRCLE) {
mPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
for (int i = 0; i < 10; i++) {
mPath.addCircle(mAnimatorValue * mwidth / 2 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 2 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 3 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 3 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 4 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 4 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 5 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 5 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
mPath.addCircle(mAnimatorValue * mwidth / 6 * (float) Math.cos(30 * i), mAnimatorValue * mwidth / 6 * (float) Math.sin(30 * i), 16, Path.Direction.CW);
}
canvas.drawPath(mPath, mPaint);
} else if (mcurrentType == Type.ROUND) {
mPaint.setStyle(Paint.Style.FILL);
Path path = new Path();
path.addCircle(0, 0, radius, Path.Direction.CW); // 添加一个圆形
PathMeasure pathMeasure = new PathMeasure(path, false);
pathMeasure.getPosTan(pathMeasure.getLength() * mAnimatorValue, pos, tan);
// mPath = new Path();
//使用 Math.atan2(tan[1], tan[0]) 将 tan 转化为角(单位为弧度)的时候要注意参数顺序。
float angle = (float) Math.atan2(tan[1], tan[0]);
for (int i = 0; i < roundCount; i++) {
//用path一次性画的,透明度不好设置
// mPath.addCircle((float) (Math.cos(angle + i*0.4) * 100), (float) (Math.sin(angle+ i*0.4) * 100), 16, Path.Direction.CW);
mPaint.setAlpha(onealpha * i);
canvas.drawCircle((float) (Math.cos(angle + i * 0.4) * radius), (float) (Math.sin(angle + i * 0.4) * radius), circleRadius, mPaint);
}
// canvas.drawPath(mPath, circlePaint);
}
break;
case SUCCES:
canvas.drawCircle(0, 0, radius, textPaint);
canvas.drawLine(-radius / 2, 0, 0, radius / 2, textPaint);
canvas.drawLine(0, radius / 2, radius / 2, -radius / 2, textPaint);
break;
case ERROR:
canvas.drawCircle(0, 0, radius, textPaint);
canvas.drawLine(radius / 2, radius / 2, -radius / 2, -radius / 2, textPaint);
canvas.drawLine(radius / 2, -radius / 2, -radius / 2, radius / 2, textPaint);
break;
default:
break;
}
}
/**
* 添加到activity的上层并执行动画
* @param activity
*
*/
public void addPartentViewStartLoading(Activity activity) {
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//Activity中View布局的最祖宗布局,是一个FrameLayout,叫做DecorView,通过getWindow().getDecorView()可以获取到
FrameLayout view = (FrameLayout) activity.getWindow().getDecorView();
view.addView(this,layoutParams);
startLoading();
}
/**
* 设置loading开始
*/
public void startLoading() {
if (loadingvalueAnimator != null) {
mcurrentState = State.LODING;
addLoadingListener();
successvalueAnimator.removeAllListeners();
errorvalueAnimator.removeAllListeners();
//如果是gone --->VISIBLE
if (this.getVisibility() == GONE) {
this.setVisibility(VISIBLE);
}
loadingvalueAnimator.start();
}
}
/**
* 成功
*/
public void setSuccess() {
loadingvalueAnimator.removeAllListeners();
errorvalueAnimator.removeAllListeners();
addSuccesLoadingListener();
successvalueAnimator.start();
}
/**
* 失败
*/
public void setError() {
loadingvalueAnimator.removeAllListeners();
successvalueAnimator.removeAllListeners();
addErrorLoadingListener();
errorvalueAnimator.start();
}
/**
* 整个事件的消费来保证loading状态不可操作
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
/**
* 设置loading的背景颜色
* @param backgroudColor
*/
public void setBackgroudColor(int backgroudColor) {
this.backgroudColor = backgroudColor;
}
/**
*
* @param mpaintColor
*/
public void setMpaintColor(int mpaintColor) {
this.mpaintColor = mpaintColor;
}
/**
*
* @param mpaintStrokeWidth
*/
public void setMpaintStrokeWidth(float mpaintStrokeWidth) {
this.mpaintStrokeWidth = mpaintStrokeWidth;
}
/**
*
* @param textPaintColor
*/
public void setTextPaintColor(int textPaintColor) {
this.textPaintColor = textPaintColor;
}
/**
*
* @param textPaintStrokeWidth
*/
public void setTextPaintStrokeWidth(float textPaintStrokeWidth) {
this.textPaintStrokeWidth = textPaintStrokeWidth;
}
/**
*
* @param textPaintTextSize
*/
public void setTextPaintTextSize(float textPaintTextSize) {
this.textPaintTextSize = textPaintTextSize;
}
/**
*
* @param radius
*/
public void setRadius(float radius) {
this.radius = radius;
}
/**
*
* @param circleRadius
*/
public void setCircleRadius(float circleRadius) {
this.circleRadius = circleRadius;
}
/**
*
* @param roundCount
*/
public void setRoundCount(int roundCount) {
this.roundCount = roundCount;
}
/**
*
* @param mcurrentType
*/
public void setType(Type mcurrentType){
this.mcurrentType=mcurrentType;
}
}

最后为大家献上自定义view————loading框 github demo,后期会将loading框优化,添加各种样式

坚持原创技术分享,您的支持将鼓励我继续创作!
Fork me on GitHub