Android折线图

192 阅读2分钟

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!

重写View的onMeasure方法 在自定义控件的时候,控件的宽高(最终的测量尺寸)由控件本身和其父容器共同决定的,既然是共同决定的我们得知道父容器的“意愿”对吧!

父容器的“意愿”也就三种,在MeasureSpec类中的三个常量表明了其三种意愿:

1、UNSPECIFIED:父容器对控件的大小不在意,你想多大都可以;

2、AT_MOST:父容器给控件的大小设置了一个最大值,表示你大小的取值最好在这个范围内;

3、EXACTLY: 父容器已经给控件计算出了显示的大小,控件就显示这么大得了;

onMeasure方法具体的代码:

int resultWidth;
    //获取父容器的意愿
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);

    if (widthMode == MeasureSpec.EXACTLY) {
        resultWidth = sizeWidth;
    } else {
        if (widthMode == MeasureSpec.AT_MOST) {
            resultWidth = Math.min(screenWidth, sizeWidth);
        } else {
            resultWidth = screenWidth;
        }
    }
    int resultHeight;

    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);

    if (heightMode == MeasureSpec.EXACTLY) {
        resultHeight = sizeHeight;
    } else {
        if (heightMode == MeasureSpec.AT_MOST) {
            resultHeight = Math.min(screenHeight, sizeHeight);
        } else {
            resultHeight = screenHeight;
        }
    }
    //设置测量出的宽高
    setMeasuredDimension(resultWidth, resultHeight);

理一下画图的顺序 drawTextY(Canvas canvas) //绘制y轴上需要显示的文字 drawTextX(Canvas canvas) //绘制x轴上的文字 drawCoordinate(Canvas canvas) //绘制坐标轴 drawBrokenLine(Canvas canvas) //绘制折线、顶点及顶点文字 差不多就是这个从上到下的顺序! 看到这儿估计有人会说:你特么逗我么,绘制折线图不先画坐标轴? 道友别急,请听我狡辩:绘制折线图有一个关键点是确定点的坐标(特么不是废话么),之所以将坐标轴放到文字之后绘制是因为y上绘制文字的宽度和x轴上文字的高度会对坐标轴的定位有一定影响。因为这两个数据是未知的,所以我们得先确定下来才好进行下一步操作!

private int maxTextWidth;
//y轴每一刻度的高度
private int singleHeight;
//文字的高度
private int textHeight;

//y轴文字list
private List<String> textY;

/**
 * draw Y轴上的文字
 *
 * @param canvas
 */
private void drawTextY(Canvas canvas) {
    if (textY == null) return;

    // 文字的高度:mTextPaint.descent() - mTextPaint.ascent()
    textHeight = (int) (mTextPaint.descent() - mTextPaint.ascent());

    singleHeight = (getHeight() - paddingBottom - paddingTop - textHeight - spacing) / (textY.size() - 1);

    int xPos = paddingLeft;
    int yPos;
    for (int i = 0; i < textY.size(); i++) {
        //找出文字所需的最大宽度
        if (mTextPaint.measureText(textY.get(textY.size() - i - 1)) > maxTextWidth) {
            maxTextWidth = (int) mTextPaint.measureText(textY.get(textY.size() - i - 1));
        }

        yPos = paddingTop + singleHeight * i + textHeight / 2;

        canvas.drawText(textY.get(textY.size() - i - 1), xPos, yPos, mTextPaint);
    }
}

ok,大概关键代码就这些。

  • 效果

image.png