Android纯手工实现几种数据趋势图的自定义View(超简单,有源码)

不需要依赖第三方框架,直接使用Canvas

drawLine,drawPath,drawCircle 
复制代码

等几个简单的API即可搞定

效果图

 

源码:https://github.com/woshiwzy/trendviews

部分代码节选

onDraw 

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        w = getWidth();
        h = getHeight();
        this.coordinate_pading_v = (int) (h * this.coordinate_pading_v_percent);
        canvas.drawColor(Color.WHITE);
        mPaint.setStrokeWidth(paintSolideSmall);
        mPaint.setTextSize(label_text_size);
        int title_width = (int) mPaint.measureText(this.titlle);
        mPaint.setStyle(Style.FILL);
        mPaint.setColor(Color.BLACK);
        canvas.drawText(this.titlle, w / 2 - title_width / 2, 50, mPaint);
        // 画背景网格
        if (0 == (countListSize(mArrayListHolderAllLastYear) + countListSize(mArrayListHolderAllThisYear) +
                countListSize(mArrayListHolderLocalLastYears) + countListSize(mArrayListHolderLocalThisYears))) {
        } else {
            drawGrid(canvas);
        }
    }

drawGrid 绘制主要内容


    public void drawGrid(Canvas canvas) {
        mPaint.setColor(0x33dbdbdb);
        // 画垂直网格
        // coordinate_pading_h
        int cell_width = (w - coordinate_pading_h * 2) / (months - 1);

        this.mPointsAll.clear();
        this.mPointsLocal.clear();
        float pix_value_unit = (h - h * coordinate_pading_v_percent - coordinate_pading_b) / (this.highest - this.lowerest);

        Path pathLocalThis = new Path();//本公司今年
        pathLocalThis.reset();

        Path pathLocalLast = new Path();//本公司去年
        pathLocalLast.reset();


        Path pathAllThis = new Path();//全市场今年
        pathAllThis.reset();

        Path pathAllLast = new Path();//全市场去年
        pathAllLast.reset();


        for (int i = 0, isize = months; i < isize; i++) {
            int startX = coordinate_pading_h + i * cell_width;
            int startY = 0;
            int stopX = coordinate_pading_h + i * cell_width;
            int stopY = h;
            canvas.drawLine(startX, startY, stopX, stopY, mPaint);// 竖直网格
            canvas.drawLine(startX + cell_width / 2, startY, startX + cell_width / 2, stopY, mPaint);// 竖直网格
            if (i == 0) {
                canvas.drawLine(startX - cell_width / 2, startY, startX - cell_width / 2, stopY, mPaint);// 竖直网格
            }

            if (null != mArrayListHolderLocalThisYears && !mArrayListHolderLocalThisYears.isEmpty()) {
                //本公司今年
                if (i < mArrayListHolderLocalThisYears.size()) {
                    Holder holderLocalThisYear = mArrayListHolderLocalThisYears.get(i);
                    if (null == this.mPointsLocal) {
                        this.mPointsLocal = new ArrayList<MyPoint>();
                    }
                    int x = startX;
                    float y = h - pix_value_unit * (holderLocalThisYear.getValue() - this.lowerest) - coordinate_pading_b;
                    MyPoint mypointlocalthisyear = new MyPoint(x, (int) y, holderLocalThisYear);
                    if (i == 0) {
                        pathLocalThis.moveTo(x, y);
                    } else {
                        pathLocalThis.lineTo(x, y);
                    }
                    this.mPointsLocal.add(mypointlocalthisyear);
                } else {
                    this.mPointsLocal = null;
                }
            }
            if (null != mArrayListHolderLocalLastYears && !mArrayListHolderLocalLastYears.isEmpty()) {
                //本公司去年
                if (i < mArrayListHolderLocalLastYears.size()) {
                    Holder holderLocalLastYear = mArrayListHolderLocalLastYears.get(i);
                    if (null == this.mPointsLast) {
                        this.mPointsLast = null;
                    }
                    int x = startX;
                    float y = h - pix_value_unit * (holderLocalLastYear.getValue() - this.lowerest) - coordinate_pading_b;
                    MyPoint mypointlocallastyear = new MyPoint(x, (int) y, holderLocalLastYear);
                    if (i == 0) {
                        pathLocalLast.moveTo(x, y);
                    } else {
                        pathLocalLast.lineTo(x, y);
                    }
                    this.mPointsLast.add(mypointlocallastyear);
                } else {
                    this.mPointsLast = null;
                }
            }

            if (null != mArrayListHolderAllThisYear && !mArrayListHolderAllThisYear.isEmpty()) {
                //全市场今年
                if (i < mArrayListHolderAllThisYear.size()) {
                    Holder holderAllHolderThisYear = mArrayListHolderAllThisYear.get(i);
                    if (null == this.mPointsAll) {
                        this.mPointsAll = new ArrayList<MyPoint>();
                    }
                    int x = startX;
                    float y = h - pix_value_unit * (holderAllHolderThisYear.getValue() - this.lowerest) - coordinate_pading_b;
                    MyPoint mypointallthisyear = new MyPoint(x, (int) y, holderAllHolderThisYear);
                    if (i == 0) {
                        pathAllThis.moveTo(x, y);
                    } else {
                        pathAllThis.lineTo(x, y);
                    }
                    this.mPointsAll.add(mypointallthisyear);
                } else {
                    this.mPointsAll = null;
                }
            }

            if (null != mArrayListHolderAllLastYear && !mArrayListHolderAllLastYear.isEmpty()) {
                //全市场去年
                if (i < mArrayListHolderAllLastYear.size()) {
                    Holder holderAllHolderLastYear = mArrayListHolderAllLastYear.get(i);
                    if (null == this.mPointsAllLast) {
                        this.mPointsAllLast = new ArrayList<MyPoint>();
                    }
                    int x = startX;
                    float y = h - pix_value_unit * (holderAllHolderLastYear.getValue() - this.lowerest) - coordinate_pading_b;
                    MyPoint mypointalllastyear = new MyPoint(x, (int) y, holderAllHolderLastYear);
                    if (i == 0) {
                        pathAllLast.moveTo(x, y);
                    } else {
                        pathAllLast.lineTo(x, y);
                    }
                    this.mPointsAllLast.add(mypointalllastyear);
                } else {
                    this.mPointsAllLast = null;
                }
            }
        }

        //组装path结束
        // 画水平网格
        int cell_height = h / (months * 2);
        for (int i = 0, isize = months * 2; i <= isize; i++) {
            canvas.drawLine(0, cell_height * i, w, cell_height * i, mPaint);
        }
        mPaint.setStyle(Style.STROKE);
        mPaint.setStrokeWidth(radiusBig);

        mPaint.setColor(0xff667788);//
        canvas.drawPath(pathLocalThis, mPaint);

        mPaint.setColor(0xff908765);//
        canvas.drawPath(pathLocalLast, mPaint);

        mPaint.setColor(0xff114477);//
        canvas.drawPath(pathAllThis, mPaint);

        mPaint.setColor(0xff765432);//
        canvas.drawPath(pathAllLast, mPaint);

        mPaint.setColor(0xffdbe4e6);
        mPaint.setStyle(Style.FILL);

        // canvas.drawLine(0, h-coordinate_pading_b, w, h-coordinate_pading_b, mPaint);
        canvas.drawRect(0, h - coordinate_pading_b / 2, w, h, mPaint);// 标注x刻度
        mPaint.setColor(Color.BLACK);
        mPaint.setTextSize((label_text_size / 3) * 2);

        ArrayList<MyPoint> locationPoints = getNotNullPointList();
        if (locationPoints != null) {
            for (int i = 0, isize = months; i < isize; i++) {
                MyPoint p = locationPoints.get(i);
                canvas.drawText(p.getHolder().getStamp(), p.x - 5, h - coordinate_pading_b / 2 + 25, mPaint);
            }
        }

        mPaint.setStrokeWidth(paintSolideBig / 2);
        mPaint.setColor(0xffb0b9c2);// 底部分割线
        canvas.drawLine(0, h, w, h, mPaint);
        mPaint.setStrokeWidth(paintSolideBig);

        if (isSetting) {
            ArrayList<MyPoint> templist = getNotNullPointList();
            if (null != templist) {
                // 找到第一个点
                if (this.startIndex < templist.size()) {
                    MyPoint startPoint = templist.get(this.startIndex);
                    drawMoveLine(canvas, startPoint, cell_width);
                    //画第二根线
                    if (endIndex < startIndex) {
                        endIndex = startIndex + 1;
                    }
                    if (endIndex < templist.size() && templist.size() > 1) {
                        MyPoint endPoint = templist.get(endIndex);
                        drawMoveLine(canvas, endPoint, cell_width);
                        drawRectransparent(canvas, startPoint, endPoint);
                    }

                }
            }
        } else {
            ArrayList<MyPoint> notNullPoints = getNotNullPointList();
            Object rets[] = findNearestPoint(notNullPoints);
            if (rets.length > 1) {
                MyPoint nearestPoint = (MyPoint) rets[0];//最近的触摸点
                //第一个点距离触摸点的
                if (1 == notNullPoints.size()) {
                    mPaint.setColor(0xff34DE71);
                    drawMoveLine(canvas, nearestPoint, cell_width);
                } else {
                    if (startIndex < 0) {
                        startIndex = 0;
                    }
                    if (endIndex < startIndex) {
                        endIndex = startIndex + 1;
                    }
                    if (endIndex >= notNullPoints.size()) {
                        endIndex = notNullPoints.size() - 1;
                    }
                    if (startIndex >= 0 && startIndex < endIndex) {
                        //找到离触摸点最近的点
                        float dstart = cputeDistanceX(mTouchPoint, notNullPoints.get(this.startIndex));
                        float dend = cputeDistanceX(mTouchPoint, notNullPoints.get(this.endIndex));
                        int index = (Integer) rets[1];
                        if (dstart < dend) {
                            //将起始点移动到触摸点	,备注:效果图要求不移动
                            this.startIndex = index;
                        }
                        if (dstart > dend) {
                            //将结束点移动到触摸点
                            this.endIndex = index;
                        }
                        MyPoint startPoint = notNullPoints.get(this.startIndex);
                        MyPoint endPoint = notNullPoints.get(this.endIndex);
                        drawMoveLine(canvas, startPoint, cell_width);//画第一根线
                        drawMoveLine(canvas, endPoint, cell_width);//画第二根线
                        drawRectransparent(canvas, startPoint, endPoint);//画半透明区域
                    }
                }
                if (null != moveListener) {
                    moveListener.onMove(this.endIndex);
                }
            }
        }


    }

猜你喜欢

转载自blog.csdn.net/wang382758656/article/details/123524039