写一个android图表框架1

1,141 阅读2分钟

前言

  • 在两年前,做过一个几乎全部是图表展示的App,当时真是一脸懵逼。找来找去找到了MpAndroidChart这个框架,在使用这个框架一个多月的时间里面,对Canvas慢慢的认识了,后面接触Html5 的Canvas,发现有点触类旁通的感觉。有一天,我无聊,上班实在没事,觉得我应该也可以写个小图表。写着写着,我发现越写越多。绘图其实没有想象中复杂。
  • github.com/huangyanbin…

图表基本结构

  • 如何画一个图表,首先要了解一个图表的基本属性,大概就是这样的。
    [

    我们想着这么画出来呢?

框架基础

  • 假设让我们绘制这个图表,首先来分析一下,最外面是标题,然后是Legend(图例),坐标,最后是图表内容。好了,我们可以想到BaseChart里面有哪些成员了,(标题,图例,坐标,内容)。我们新建一个BaseChart extends view.

绘制图表标题

  • 通过onSizeChanged()方法我们可以拿到View的大小,然后可以得到BaseChart的Rect即(0,0,width,height).新建一个类BaseChartTitle,我们定义4个常量代表Title位置。然后定义一个percent,标题占比多少。提供set get方法。
    int LEFT = 0;
    int TOP = 1;
    int RIGHT =2;
    int BOTTOM = 3;
  • 开始绘制标题,首先通过计算我们已经得到startX,startY,通过paint得到文字长度和宽度。
   @Override
    public void drawTitle(Canvas canvas, Rect rect, Paint paint) {
        fontStyle.fillPaint(paint);

        String chartName = chartData.getChartName();
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        float textHeight = fontMetrics.descent - fontMetrics.ascent;
        int textWidth = (int)paint.measureText(chartName);
        int startX,startY;
        Path path = new Path();
        switch (titleDirection) {
            case TOP:
                startY = (int) (rect.top + rect.height() * percent/2);
                startX = rect.centerX();
                startY-= textHeight/2;
                startX -=textWidth/2;
                canvas.drawText(chartName, startX, startY, paint);
                break;
            case LEFT:
                startX = (int) (rect.left +  rect.width() * percent/2);
                startX -= textWidth/2;
                path.moveTo(startX,rect.top);
                path.lineTo(startX,rect.bottom);
                canvas.drawTextOnPath(chartName,path,rect.width()/2-textWidth/2,0,paint);
                break;
            case RIGHT:
                startX = (int) (rect.right - rect.width()* percent/2);
                startX -= textHeight/2;
                path.moveTo(startX,rect.top);
                path.lineTo(startX,rect.bottom);
                canvas.drawTextOnPath(chartName,path,rect.width()/2-textWidth/2,0,paint);
                break;
            case BOTTOM:
                startY = (int) (rect.bottom - rect.height() * percent/2);
                startX =  rect.centerX();
                startY -= textHeight/2;
                startX -=textWidth/2;
                canvas.drawText(chartName, startX, startY, paint);
                break;
        }

    }
  • 当Left和Right绘制标题时,应该是竖向的,所以用canvas.drawTextOnPath方法,当Top和Bottom时,可以使用canvas.drawText方法。