老规矩,先来一波效果图
再来看看具体实现
首先肯定要先画一个背景
我是通过判断值的大小来改变背景的颜色
private void drawBgCircle(Canvas canvas) {
if (progress <= 25 && progress >= 0) {
mPaintInnerCircle.setColor(Color.parseColor("#55EA4602"));
} else if (progress > 25 && progress <= 50) {
mPaintInnerCircle.setColor(Color.parseColor("#55F48600"));
} else if (progress > 50 && progress <= 75) {
mPaintInnerCircle.setColor(Color.parseColor("#55A8D309"));
} else {
mPaintInnerCircle.setColor(Color.parseColor("#5548B619"));
}
canvas.drawCircle(mCenterXY, mCenterXY, mRadius, mPaintInnerCircle);
}
然后再画外边缘的线
/**
* 实现画刻度线的功能
*/
private void drawLine(final Canvas canvas) {
// 保存之前的画布状态
canvas.save();
// 移动画布,实际上是改变坐标系的位置
canvas.translate(mCenterXY, mCenterXY);
// canvas.rotate(30);
// 设置画笔的宽度(线的粗细)
linePaint.setStrokeWidth(UIUtils.sp2px(1));
// 累计叠加的角度
float c = 0;
float a = sweepAngle / 100;
for (int i = 0; i <= 100; i++) {
if (c <= sweepAngle) {// 如果累计画过的角度,小于当前有效刻度
if (i == 0 || i == 100) {
double p = c / (double) sweepAngle;
int red = 255 - (int) (p * 255);
int green = (int) (p * 255);
linePaint.setARGB(255, red, green, 50);
canvas.drawLine(0, mRadius + 20, 0, mRadius + 60, linePaint);
} else {
double p = c / (double) sweepAngle;
int red = 255 - (int) (p * 255);
int green = (int) (p * 255);
linePaint.setARGB(255, red, green, 50);
canvas.drawLine(0, mRadius + 20, 0, mRadius + 50, linePaint);
}
// 画过的角度进行叠加
c += a;
} else {
linePaint.setColor(Color.GREEN);
canvas.drawLine(0, mRadius + 20, 0, mRadius + 60, linePaint);
}
canvas.rotate(a);
}
// 恢复画布状态。
canvas.restore();
}
然后画文字
private void drawText(Canvas canvas) {
//绘制中心的文字
String text = progress + "%";
mPaintText.getTextBounds(text, 0, text.length(), mRectProgress);
canvas.drawText(text, (getWidth() - mRectProgress.width()) / 2, (getHeight() + mRectProgress.height()) / 2, mPaintText);
//绘制tips的文字
canvas.drawText(mTipString, (getWidth() - mRectTips.width()) / 2, (getHeight() / 2 + mRectProgress.height()) / 2, mPaintTextTips);
}
最后看来看看如何画波浪
首先通过path来创建波浪的线条(这段代码是复制的,难点就在这里)
/**
* 创建波浪,主要是通过path来创建
*/
private void createWavePath(int progress) {
mPath.reset();
float absY;
float sweepAngle;
float startAngle;
float absX;
if (progress >= 50) {
absY = mRadius * 2 * (progress * 1.0f / 100);
float angle = (float) (Math.asin((absY - mRadius) * 1.0f / mRadius) * 180 / Math.PI);
absX = (float) (mRadius * Math.cos(angle * Math.PI / 180));
sweepAngle = angle * 2 + 180;
startAngle = -angle;
} else {
absY = mRadius * 2 * (progress * 1.0f / 100);
float angle = (float) (Math.acos((mRadius - absY) * 1.0f / mRadius) * 180 / Math.PI);
absX = (float) (mRadius * Math.sin(angle * Math.PI / 180));
sweepAngle = angle * 2;
startAngle = 90 - angle;
}
int startX = (int) (mRadius - absX) + mStrokeWidth;
float x, y;
for (int i = 0; i < absX * 2; i++) {
x = i + startX;
y = (float) (mWaveHeight * Math.sin((i * 1.5f + mOffsetX) / mRadius * Math.PI)) + (mRadius * 2 - absY) + mStrokeWidth;
if (i == 0) {
mPath.moveTo(x, y);
} else {
mPath.quadTo(x, y, x + 1, y);
}
}
RectF rectF = new RectF(mStrokeWidth, mStrokeWidth, mRadius * 2 + mStrokeWidth, mRadius * 2 + mStrokeWidth);
mPath.arcTo(rectF, startAngle, sweepAngle);
mPath.close();
}
然后开始绘制
private void drawnWaveSetPaint(Canvas canvas) {
if (progress <= 25 && progress >= 0) {
mPaintWater.setColor(Color.parseColor("#EA4602"));
} else if (progress > 25 && progress <= 50) {
mPaintWater.setColor(Color.parseColor("#F48600"));
} else if (progress > 50 && progress <= 75) {
mPaintWater.setColor(Color.parseColor("#A8D309"));
} else {
mPaintWater.setColor(Color.parseColor("#48B619"));
}
canvas.drawPath(mPath, mPaintWater);
}
最后提供两个开启动画和关闭动画的方法
/**
* 设置进度
*/
public void setProgress(int progress) {
if (progress < 0) {
this.progress = 0;
} else {
this.progress = progress;
}
invalidate();
}
/**
* 开始动画
*/
public void startWave() {
if (!isWaving && mHandler != null) {
mHandler.sendEmptyMessage(10);
}
isWaving = true;
}
/**
* 关闭动画
*/
public void stopWave() {
if (mHandler != null) {
mHandler.removeMessages(10);
}
isWaving = false;
}
创建handler
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mOffsetX = mOffsetX + 8;
if (mOffsetX > 10000) {
mOffsetX = 0;
}
invalidate();
}
};
搞定!!!!!!!!!!!!!!!!!!!!!!1