//参考了 http://blog.csdn.net/qfanmingyiq/article/details/53038262
public class MyBDView extends View {
// 波纹颜色
private static final int WAVE_PAINT_COLOR = 0x33c0c0c0;
// 底部的高度 注意 底部高度要大于最大的振幅
private static int BOTTOM_HIGH = 40;
// 第一个波纹移动的速度
private int oneSeep = 7;
// 第二个波纹移动的速度
private int twoSeep = 13;
// 第一个波纹移动速度的像素值
private int oneSeepPxil;
// 第二个波纹移动速度的像素值
private int twoSeepPxil;
// 存放原始波纹的每个y坐标点
private float wave1[];
private float wave2[];
// 存放第一个波纹的每一个y坐标点
private float oneWave[];
// 存放第二个波纹的每一个y坐标点
private float twoWave[];
// 第一个波纹当前移动的距离
private int oneNowOffSet;
// 第二个波纹当前移动的
private int twoNowOffSet;
// 振幅高度
private int amplitude1 = 27;
private int amplitude2 = 19;
// 画笔
private Paint mPaint;
private Paint mPaintStop;
// 创建画布过滤
private DrawFilter mDrawFilter;
// view的宽度
private int viewWidth;
// view高度
private int viewHeight;
//
private boolean flag = false;
//开始波动
public void start() {
flag = true;
postInvalidate();
}
//停止波动
public void stop() {
flag = false;
}
// xml布局构造方法
public MyBDView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
// 初始化
private void init() {
// 创建画笔
mPaint = new Paint();
// 设置画笔颜色
mPaint.setColor(WAVE_PAINT_COLOR);
// 设置绘画风格为实线
mPaint.setStyle(Paint.Style.FILL);
// 抗锯齿
mPaint.setAntiAlias(true);
// 设置划线的粗细
mPaint.setStrokeWidth(4);
// 设置图片过滤波和抗锯齿
mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
// 第一个波的像素移动值 换算成手机像素值让其在各个手机移动速度差不多
oneSeepPxil = dpChangPx(oneSeep);
// 第二个波的像素移动值
twoSeepPxil = dpChangPx(twoSeep);
// 创建画笔
mPaintStop = new Paint();
// 设置画笔颜色
mPaintStop.setColor(WAVE_PAINT_COLOR);
// 设置绘画风格为实线
mPaintStop.setStyle(Paint.Style.FILL);
// 抗锯齿
mPaint.setAntiAlias(true);
// 设置图片过滤波和抗锯齿
// mDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
}
// 绘画方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.setDrawFilter(mDrawFilter);
oneNowOffSet = oneNowOffSet + oneSeepPxil;
twoNowOffSet = twoNowOffSet + twoSeepPxil;
if (oneNowOffSet >= viewWidth) {
oneNowOffSet = 0;
}
if (twoNowOffSet >= viewWidth) {
twoNowOffSet = 0;
}
// 设置波动开始于结束的标记
if (flag) {
reSet();
//i每次 增加4
for (int i = 0; i < viewWidth; i = i + 4) {
canvas.drawLine(i, viewHeight, i, viewHeight - BOTTOM_HIGH - oneWave[i], mPaint);
canvas.drawLine(i, viewHeight, i, viewHeight - BOTTOM_HIGH - twoWave[i], mPaint);
}
// 睡眠 10 减少cup 使用 自己测试 配合 上面i +4 在只用这一个控件的情况下 (自己测试)大概减少40% 的cup使用
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
postInvalidate();
} else {
for (int i = 0; i < viewWidth; i++) {
canvas.drawLine(i, viewHeight, i, viewHeight - BOTTOM_HIGH - oneWave[i], mPaintStop);
canvas.drawLine(i, viewHeight, i, viewHeight - BOTTOM_HIGH - twoWave[i], mPaintStop);
}
}
}
private void reSet() {
// one是指 走到此处的波纹的位置 (这个理解方法看个人了)
int one = viewWidth - oneNowOffSet;
// 把未走过的波纹放到最前面 进行重新拼接
System.arraycopy(wave1, oneNowOffSet, oneWave, 0, one);
// 把已走波纹放到最后
System.arraycopy(wave1, 0, oneWave, one, oneNowOffSet);
// one是指 走到此处的波纹的位置 (这个理解方法看个人了)
int two = viewWidth - twoNowOffSet;
// 把未走过的波纹放到最前面 进行重新拼接
System.arraycopy(wave2, twoNowOffSet, twoWave, 0, two);
// 把已走波纹放到最后
System.arraycopy(wave2, 0, twoWave, two, twoNowOffSet);
}
// 大小改变
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// 获取view的宽高
viewHeight = h;
viewWidth = w;
// 初始化保存波形图的数组
wave1 = new float[w];
wave2 = new float[w];
oneWave = new float[w];
twoWave = new float[w];
// 设置波形图周期
float zq1 = (float) (Math.PI * 4 / w);
// 设置波形图的周期
for (int i = 0; i < viewWidth; i++) {
wave1[i] = (float) (amplitude1 * Math.sin(zq1 * i));
wave2[i] = (float) (amplitude2 * Math.sin(zq1 * i));
}
}
// dp换算成px 为了让移动速度在各个分辨率的手机的都差不多
private int dpChangPx(int dp) {
DisplayMetrics metrics = new DisplayMetrics();
((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(metrics);
return (int) (metrics.density * dp + 0.5f);
}
}