Android 自定义view绘制折线图

个人记录使用
新建类,继承view
重写ondraw方法;
带2组Y轴坐标(数据超过一定值则用大的那组)
同步更新的X轴坐标
Y轴有小横线标。
X轴和数据点都有圆点。
懒得截图了。效果就是普通的折线图。(不过丑了点)

    private Paint STROKEpaint = new Paint();
    private Paint FILLpaint = new Paint();
    private LinkedList ls = new LinkedList();
    private String[] str = { "    0", "  20", "  40", "  60", "  80" };
    private String[] strbig = { "    0", "200", "400", "600", "800" };
    float TH, TX, YT, XT, BFBY;
    private LinkedList sj = new LinkedList();

    @Override
    protected void onDraw(Canvas canvas) {
        TH = getHeight() - 20;//为高度上下做预留,方便文字的显示
        TX = getWidth() - 20;//为宽度左右做预留,方便文字的显示
        STROKEpaint.setAntiAlias(true);//抗锯齿,关了线很丑
        STROKEpaint.setStyle(Paint.Style.STROKE);//设置画笔为空心
        STROKEpaint.setStrokeWidth(1);//设置空心线宽
        STROKEpaint.setTextSize(12);//设置字体大小
        FILLpaint.setAntiAlias(true);
        FILLpaint.setStyle(Paint.Style.FILL);//设置画笔为实心
        FILLpaint.setStrokeWidth(1);
        canvas.drawLine(20, 0, 20, getHeight(), STROKEpaint);//画Y轴线
        canvas.drawLine(0, TH, getWidth(), TH, STROKEpaint);//画X轴线
        YT = (float) (TH / 5.0);//Y轴有5段长,0~100,这里先把坐标轴的一份分出来
        XT = (float) (TX / 8.0);//同理,不过X轴分为7段
        for (int i = 0; i < ls.size(); i++) {
            float value = ls.get(i);
            if (value > 100) {
                BFBY = (float) (TH / 1000.0);//计算坐标轴百分比,遍历列表里有没有超过100的数据,如果有就用1000的百分比;
                break;
            } else {
                BFBY = (float) (TH / 100.0);
            }
        }
        for (int i = 0; i < str.length; i++) {
            if (BFBY < 1) {
                canvas.drawText(strbig[i], 0, TH - (YT * i), FILLpaint);//如果是1000的百分比,那切出来的1份肯定很小(比1还小),所以这里画这里画Y轴坐标点就用1000尺度的那个数组。
            } else {
                canvas.drawText(str[i], 0, TH - (YT * i), FILLpaint);
                //没超过100就画这个
            }
        }
        for (int i = 0; i < 6; i++) {
            canvas.drawLine(20, TH - (YT * i), 25, TH - (YT * i), STROKEpaint);//Y轴坐标点旁边的小横线(25改成总宽度其实就变成网格线里的横线了),Y轴分5段,自然就有6条小横线。
        }
        for (int i = 0; i < 7; i++) {
            canvas.drawCircle((XT * (i + 1)) + 20, TH, 2, FILLpaint);//X轴上的小圆点,按照一开始就算好的单份坐标*对应的数就好了,记得加上预留20的宽度。
        }
        Path path = new Path();//定义一条线,其实这种频繁调用的方法里不应该new东西,但写外面稍微烦了点(不能只定义一条),所以就写里面了。
        for (int i = 0; i < ls.size(); i++) {
            float value = ls.get(i);//从数据源拿数据
            String show = sj.get(i);//从数据源拿X轴上对应显示的数据
            if (i == 0) {
                path.moveTo(TX - (XT * (i + 1)) + 20, TH - (value * BFBY));//第一次先用move,移动到第一个点。
            } else {
                path.lineTo(TX - (XT * (i + 1)) + 20, TH - (value * BFBY));//按着次数往下画,数据只在Y轴变化,X轴总归是那些点。
            }
            canvas.drawCircle(TX - (XT * (i + 1)) + 20, TH - (value * BFBY), 2,FILLpaint);//给数据转折的地方画点(X轴总是那些点不变,Y轴跟着变而已)
            canvas.drawText(show, TX - (XT * (i + 1)) + 15, TH + 10, FILLpaint);//给X轴画上对应的数据标准(01 02~~)之类的。
        }
        canvas.drawPath(path, STROKEpaint);//记得在for循环外面再把线画出来。。。不然会7条线叠起来,很难看。
    }

    public void start(LinkedList ls, LinkedList sj) {
        this.ls = ls;//传数据
        this.sj = sj;
        postInvalidate();//更新界面,每次获取到新数据就触发ondraw重绘。
    }

问题很多:
没有管理好ondraw画的东西(很多东西其实可以画一次,比如XY轴,但现在每次其实都重画了,加大的负担);
画图的计算方式,虽然我自己看得懂,但一眼看上去也很懵逼,有时候还得调(加加减减什么的);

注意点:
第一步,一定要给预留,不然XY轴的字没地方写了。
第二步,画布是0,0是从左上角开始的,所以其实你画一张正着的图表,都是反着来的!(但只要相减一下就好,折线是从左往右刷新还是从右往左刷新其实都是减一下就好)
第三步,要画一个能显示75.3这种数据的,每份坐标要很小,我现在是每份是1(总数100,我就/了100份),所以只能显示精确到个位的数,如果一份坐标点只有0.1,那自然可以精确到小数位

你可能感兴趣的:(记录)