手写android折线图、柱状图

2,802 阅读2分钟

项目中要使用到几个简单的图表,如下图所示

第一时间想到用MPAndroidChart,但是这个库贼大,而且api文档也不全,决定自己手写,这是手写的效果:

github地址:github.com/amusiaHzr/L… 有兴趣的同学可以看看,觉得有帮助顺手给个star吧

主要思路就是在onDraw方法中分步骤画出所需要的:点、线、path,

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //初始化一些参数
    init();
    //将所有的坐标点转成PointF,并放入list
    initPoint();
    //绘制底部文字
    drawBottomText(canvas);
    //绘制底部横线
    drawBottomLine(canvas);
    //绘制折线图背景
    drawBg(canvas);
    //绘制折线图
    drawBrokenLine(canvas);
    //绘制折线图上的文字
    drawTopText(canvas);
}

初始化point方法:

     private void initPoint() {
        //折线图的高度 = view的高度 - 上面文字高度 - 下面文字高度
        float brokenLineHeight = mSelfHeight - topTextHeight - bottomHeight;
        //单位折线图高度 = 折线图的高度 / 数据集中最大的值
        float proportionHeight = brokenLineHeight / getMaxData();
        //初始x点坐标 = 水平方向间距 + 每个点的宽度/2 
        float circleCenterX = horizontalSpace + proportionWidth / 2;
        //初始y点坐标 = 0
        float circleCenterY;
        //使用之前clear一下,有可能执行多次onDraw
        points.clear();
        //将点放入到集合
        for (int i = 0; i < mData.length; i++) {
            float currentProportionHeight = mData[i] * proportionHeight;
            circleCenterY = mSelfHeight - bottomHeight - currentProportionHeight;
            points.add(new PointF(circleCenterX, circleCenterY));
            circleCenterX += proportionWidth;
        }
    }

画底部文字

    /**
     * 画底部文字
     *
     * @param canvas
     */
    private void drawBottomText(Canvas canvas) {
        //文字初始点x坐标
        float currentTextX = 0;
        //文字初始点y坐标
        float currentTextY = 0;
        currentTextX = proportionWidth / 2 + horizontalSpace;
        currentTextY = mSelfHeight - verticalSpace;
        mPaint.setTextSize(DisplayUtils.sp2px(getContext(), 13));
        mPaint.setColor(Color.parseColor("#666666"));
        mPaint.setTextAlign(Paint.Align.CENTER);
        for (int i = 0; i < mYears.length; i++) {
            //currentTextX左边起始点,currentTextY文字基线坐标
            canvas.drawText(mYears[i], currentTextX, currentTextY, mPaint);
            currentTextX += proportionWidth;
        }
}

大概就是这么个思路,将复杂的view分解成一个个小部分,分别将它们绘制出来就好了,有兴趣的朋友可以去github看看源码。

还有一个可以自定义内容的android流式布局:github.com/amusiaHzr/a… 可以通过 implementation 直接使用

效果图: