1 用户场景
用户想知晓冷热量消耗的情况
2 功能需求
当前本月已用的能耗计量值、本月基础套餐里的免费额度值、以天为粒度的用能曲线图呈现
3 关键实现
3.1 绘制方格竖直线
// 设置绘制方格线背景时用到的画笔
Paint paint = new Paint();
paint.setColor(Color.parseColor("#1FFFFFFF"));
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1.0f);
// 格子宽度
float plaidWidth = mCanvasWidth / ((float) mVerticalLineNum);
// 竖直线的x坐标
float row = (float) 0;
while (row < mCanvasWidth) {
canvas.drawLine(row, (float) 0, row, mCanvasHeight, paint);
row += plaidWidth;
if (row >= mCanvasWidth) {
canvas.drawLine(mCanvasWidth - 1.0f, (float) 0, mCanvasWidth - 1.0f, mCanvasHeight, paint);
}
}
3.2 绘制方格水平线
float column = 0.0f;
// 五分之一格子高度
float plaidHeightExtra = (mCanvasHeight / ((float) mHorizontalLineNum)) / 5.0f;
// 格子高度
float plaidHeight = (mCanvasHeight - plaidHeightExtra) / ((float) mHorizontalLineNum);
while (true) {
if (column >= mCanvasHeight) {
break;
}
float plaidHeightTemp = column + plaidHeight;
if (plaidHeightTemp > mCanvasHeight) {
canvas.drawLine((float) 0, mCanvasHeight - 1.0f, mCanvasWidth, mCanvasHeight - 1.0f, paint);
} else {
float temp = plaidHeightExtra + column;
canvas.drawLine((float) 0, temp, mCanvasWidth, temp, paint);
}
column = plaidHeightTemp;
}
3.3 绘制基准线
if (mBaseValue != 0) {
// 基准线y坐标
float f11 = ((float) (LineChartView.STANDARD_VALUE - mBaseValue)) * (mCanvasHeight / ((float) LineChartView.STANDARD_VALUE));
paint.setColor(Color.parseColor("#FFFF0000"));
canvas.drawLine((float) 0, f11, mCanvasWidth, f11, paint);
RectF rectF = new RectF();
rectF.left = 0;
rectF.right = plaidWidth;
rectF.top = (f11 - (plaidHeight * 0.2f)) - 10.0f;
rectF.bottom = f11 - 10.0f;
float f12 = plaidWidth * 0.2f;
paint.setStyle(Paint.Style.FILL);
canvas.drawRoundRect(rectF, f12, f12, paint);
Paint.FontMetrics fontMetrics = paint.getFontMetrics();
float centerY = rectF.centerY() + (((fontMetrics.bottom - fontMetrics.top) / 2.0f) - fontMetrics.bottom);
paint.setColor(-1);
// paint.setStyle(Paint.Style.STROKE);
paint.setTextSize(12.0f);
paint.setTextAlign(Paint.Align.CENTER);
paint.setAntiAlias(true);
canvas.drawText("基础套餐", rectF.centerX(), centerY, paint);
}
3.4 设置点的数组
mPoints = new Point[mValues.length];
float length = mCanvasWidth / ((float) (mMaxDate - 1));
for (int i9 = 0; i9 < mValues.length; i9++) {
Point point = new Point();
int i10 = LineChartView.STANDARD_VALUE;
point.y = (int) (((float) (i10 - this.mValues[i9])) * (mCanvasHeight / ((float) i10)));
point.x = (int) (((float) i9) * length);
this.mPoints[i9] = point;
}
3.5 绘制曲线
private void drawLinePath(Canvas canvas, Paint paint) {
Canvas canvas2 = canvas;
Paint paint2 = paint;
paint2.setColor(-16776961);
paint2.setStrokeWidth(2.0f);
paint2.setStyle(Paint.Style.FILL);
paint2.setTextSize(16.0f);
new Point();
new Point();
int i = 0;
while (true) {
Point[] pointArr = this.mPoints;
if (i < pointArr.length - 1) {
Point point = pointArr[i];
int i2 = i + 1;
Point point2 = pointArr[i2];
int i3 = (point.x + point2.x) / 2;
Point point3 = new Point();
Point point4 = new Point();
point3.y = point.y;
point3.x = i3;
point4.y = point2.y;
point4.x = i3;
Path path = new Path();
Path path2 = new Path();
path.moveTo((float) point.x, (float) point.y);
int i4 = i2;
path.cubicTo((float) point3.x, (float) point3.y, (float) point4.x, (float) point4.y, (float) point2.x, (float) point2.y);
path2.moveTo((float) point.x, (float) point.y);
Path path3 = path2;
path2.cubicTo((float) point3.x, (float) point3.y, (float) point4.x, (float) point4.y, (float) point2.x, (float) point2.y);
paint2.setColor(Color.parseColor("#FFFFFFFF"));
paint2.setStyle(Paint.Style.STROKE);
paint2.setAlpha(255);
canvas2.drawPath(path, paint2);
path3.lineTo((float) point2.x, mCanvasHeight);
path3.lineTo((float) point.x, mCanvasHeight);
path3.close();
paint2.setStyle(Paint.Style.FILL);
paint2.setColor(Color.parseColor("#FFFFFFFF"));
paint2.setAlpha(50);
canvas2.drawPath(path3, paint2);
if (i == this.mPoints.length - 2) {
paint2.setColor(-1);
canvas2.drawCircle((float) (point2.x - 3), (float) (point2.y - 1), 5.0f, paint2);
// canvas2.drawLine((float) (point2.x - 3), (float) 0, (float) (point2.x - 3), mCanvasHeight, paint2);
// 绘制浮动文本
String text = mFloatText;
String[] strings = text.split("\n");
int w = 0;// 文本最长宽度
int h = 0;// 文本高度
if (strings.length == 2) {
for (String s : strings) {
Rect rect = new Rect();
paint2.getTextBounds(s, 0, s.length(), rect);
int width = rect.width();//文本的宽度
int height = rect.height();//文本的高度
if (w < width) {
w = width;
}
h += height;
}
}
// Log.i("LineChartView", "point2.x==" + point2.x + "###point2.y==" + point2.y);
float currentX = (float) (point2.x - w) - 15.0f;
float currentY = (float) (point2.y - h);
if ((float) (point2.y - h * 2.0f + 10.0f) > 0) {
if (point2.x > mCanvasWidth / 2) {
RectF rec = new RectF((float) (point2.x - (w + 10.0f)) - 10.0f, (float) (point2.y - h * 2.0f + 10.0f), (float) (point2.x) - 10.0f, (float) (point2.y));
canvas.drawRoundRect(rec, 10, 10, paint2);
} else {
RectF rec = new RectF((float) (point2.x) + 10.0f, (float) (point2.y - h * 2.0f + 10.0f), (float) (point2.x + w) + 10.0f + 10.0f, (float) (point2.y));
canvas.drawRoundRect(rec, 10, 10, paint2);
currentX = (float) (point2.x) + 15.0f;
currentY = (float) (point2.y - h);
}
} else {
if (point2.x > mCanvasWidth / 2) {
RectF rec = new RectF((float) (point2.x - (w + 10.0f)) - 10.0f, (float) (point2.y + 10.0f), (float) (point2.x) - 10.0f, (float) (point2.y) + h * 2.0f);
canvas.drawRoundRect(rec, 10, 10, paint2);
currentX = (float) (point2.x - w) - 15.0f;
currentY = (float) (point2.y + h);
} else {
RectF rec = new RectF((float) (point2.x) + 10.0f, (float) (point2.y + 10.0f), (float) (point2.x + w) + 10.0f + 10.0f, (float) (point2.y) + h * 2.0f);
canvas.drawRoundRect(rec, 10, 10, paint2);
currentX = (float) (point2.x) + 15.0f;
currentY = (float) (point2.y + h);
}
}
paint2.setColor(Color.parseColor("#ff0000"));
paint2.setTextAlign(Paint.Align.LEFT);
drawMultiLineText(text, currentX, currentY, paint2, canvas2);
}
i = i4;
} else {
return;
}
}
}
本文介绍了在Android平台上如何根据用户场景和功能需求,自定义绘制能耗曲线图。关键实现包括绘制方格竖直线、水平线、基准线,设置点的数组以及绘制曲线,提供截图和源码供参考。


1183

被折叠的 条评论
为什么被折叠?



