-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathWaveView.java
More file actions
267 lines (245 loc) · 8.43 KB
/
Copy pathWaveView.java
File metadata and controls
267 lines (245 loc) · 8.43 KB
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
package com.azhon.test;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;
/*
* 文件名: WaveView
* 创建者: ZSY
* 创建时间: 2017/8/29 on 09:10
* 描述: TODO 水波纹view 剩余流量球
*/
public class WaveView extends View {
/*画布宽度*/
private int width;
/*画布高度*/
private int height;
/*sin曲线画笔*/
private Paint paint;
/*圆的画笔*/
private Paint textPaint;
/*文本画笔*/
private Paint circlePaint;
/*sin曲线的路径*/
private Path path;
/*sin曲线 1/4个周期的宽度*/
private int cycle = 160;
/*sin曲线振幅的高度*/
private int waveHeight = 80;
/*sin曲线的起点*/
private Point startPoint;
/*当前进度*/
private int progress;
/*x轴平移量*/
private int translateX = 40;
/*是否启用了动画设置进度*/
private boolean openAnimate = false;
/*是否自增长*/
private boolean autoIncrement = true;
public WaveView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
public WaveView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
path = new Path();
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(dip2px(context, 5));
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
circlePaint = new Paint();
circlePaint.setStrokeWidth(dip2px(context, 5));
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.parseColor("#FF4081"));
textPaint = new Paint();
textPaint.setAntiAlias(true);
textPaint.setTextSize(dip2px(context, 20));
textPaint.setColor(Color.BLACK);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//裁剪画布为圆形
Path circlePath = new Path();
circlePath.addCircle(width / 2, height / 2, width / 2, Path.Direction.CW);
canvas.clipPath(circlePath);
canvas.drawPaint(circlePaint);
canvas.drawCircle(width / 2, height / 2, width / 2, circlePaint);
//以下操作都是在这个圆形画布中操作
//根据进度改变起点坐标的y值
startPoint.y = (int) (height - (progress / 100.0 * height));
//起点
path.moveTo(startPoint.x, startPoint.y);
int j = 1;
//循环绘制正弦曲线 循环一次半个周期
for (int i = 1; i <= 8; i++) {
if (i % 2 == 0) {
//波峰
path.quadTo(startPoint.x + (cycle * j), startPoint.y + waveHeight,
startPoint.x + (cycle * 2) * i, startPoint.y);
} else {
//波谷
path.quadTo(startPoint.x + (cycle * j), startPoint.y - waveHeight,
startPoint.x + (cycle * 2) * i, startPoint.y);
}
j += 2;
}
//绘制封闭的曲线
path.lineTo(width, height);//右下角
path.lineTo(startPoint.x, height);//左下角
path.lineTo(startPoint.x, startPoint.y);//起点
path.close();
canvas.drawPath(path, paint);
drawText(canvas, textPaint, progress + "%");
//判断是不是平移完了一个周期
if (startPoint.x + translateX >= 0) {
//满了一个周期则恢复默认起点继续平移
startPoint.x = -cycle * 4;
}
//每次波形的平移量 40
startPoint.x += translateX;
if (autoIncrement) {
if (progress >= 100) {
progress = 0;
} else {
progress++;
}
}
path.reset();
if (!openAnimate) {
postInvalidateDelayed(150);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取view的宽度
width = getViewSize(400, widthMeasureSpec);
//获取view的高度
height = getViewSize(400, heightMeasureSpec);
//默认从屏幕外先绘制3/4个周期 使得波峰在圆中间
startPoint = new Point(-cycle * 3, height / 2);
}
private int getViewSize(int defaultSize, int measureSpec) {
int viewSize = defaultSize;
//获取测量模式
int mode = MeasureSpec.getMode(measureSpec);
//获取大小
int size = MeasureSpec.getSize(measureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED: //如果没有指定大小,就设置为默认大小
viewSize = defaultSize;
break;
case MeasureSpec.AT_MOST: //如果测量模式是最大取值为size
//我们将大小取最大值,你也可以取其他值
viewSize = size;
break;
case MeasureSpec.EXACTLY: //如果是固定的大小,那就不要去改变它
viewSize = size;
break;
}
return viewSize;
}
/**
* 绘制文字
*
* @param canvas 画布
* @param paint 画笔
* @param text 画的文字
*/
private void drawText(Canvas canvas, Paint paint, String text) {
//画布的大小
Rect targetRect = new Rect(0, 0, width, height);
Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
// 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()
paint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, targetRect.centerX(), baseline, paint);
}
/**
* 根据手机的分辨率从 dip 的单位 转成为 px(像素)
*/
public int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 设置振幅高度
*
* @param waveHeight 振幅
*/
public void setWaveHeight(int waveHeight) {
this.waveHeight = waveHeight;
invalidate();
}
/**
* 设置sin曲线 1/4个周期的宽度
*
* @param cycle 1/4个周期的宽度
*/
public void setCycle(int cycle) {
this.cycle = cycle;
invalidate();
}
/**
* 设置当前进度
*
* @param progress 进度
*/
public void setProgress(int progress) {
if (progress > 100 || progress < 0)
throw new RuntimeException(getClass().getName() + "请设置[0,100]之间的值");
this.progress = progress;
autoIncrement = false;
invalidate();
}
/**
* 设置x轴移动量
*
* @param translateX 默认40
*/
public void setTranslateX(int translateX) {
this.translateX = translateX;
}
/**
* 通过动画设置当前进度
*
* @param progress 进度 <=100
* @param duration 动画时长
*/
public void setProgress(final int progress, int duration) {
if (progress > 100 || progress < 0)
throw new RuntimeException(getClass().getName() + "请设置[0,100]之间的值");
autoIncrement = false;
openAnimate = true;
ValueAnimator progressAnimator = ValueAnimator.ofInt(0, progress);
progressAnimator.setDuration(duration);
progressAnimator.setTarget(progress);
progressAnimator.setInterpolator(new LinearInterpolator());
progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
WaveView.this.progress = (int) animation.getAnimatedValue();
if (WaveView.this.progress == progress)
openAnimate = false;
invalidate();
}
});
progressAnimator.start();
}
public int getProgress() {
return progress;
}
}