码迷,mamicode.com
首页 > 移动开发 > 详细

Android雷达图(蜘蛛网图)

时间:2017-08-16 13:13:48      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:highlight   测量   mda   val   构造   效果图   方式   []   ext   

简介

最近因为项目的需要,需要实现雷达图来展示各科目的对题率。

雷达图的绘制不算复杂,只要按照一定的流程来绘制就可以了,其中使用的最多的是path路径类,使用这个类便于我们绘制出多边形等效果。

效果图如下:

技术分享

使用方式

使用方式很简单,直接在布局文件里面使用这个控件,记得设置一个合适的大小就可以。

当然也有开放一些public方法,可以进行数据、文本颜色等设置。

    /**
     * 设置数据
     * @param points
     */
    public void setData(ArrayList<LastPoint> points){}

    /**
     * 设置文本
     * @param titles
     */
    public void setTitles(String[] titles){}

    /**
     * 设置圈数
     * @param count
     */
    public void setCount(int count){}

    /**
     * 设置网格线颜色
     * @param color
     */
    public void setLineColor(int color){}

    /**
     * 设置填充区域颜色
     * @param color
     */
    public void setValueColor(int color){}

    /**
     * 设置文本颜色
     * @param color
     */
    public void setTextColor(int color){}

具体实现

一般自定义控件的流程有以下几个步骤(个人观点):

* 1、构造函数(初始化)
* 2、onMeasure(测量大小)
* 3、onSizeChanged(确定大小)
* 4、onLayout(子view的位置,如果包含子view的话)
* 5、onDraw(绘制内容)
* 6、暴露给外部的接口

在该控件中,2、4都不用考虑,只要确定了大小(onSizeChanged),就能够计算出整个布局的中心,雷达图是以这个中心开始绘制的。

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
     //中心坐标 mCenterX = mWidth/2; mCenterY = mHeight/2; mRadius = (Math.min(mWidth,mHeight)/2 * 0.9f); postInvalidate(); }

  

绘制蜘蛛网图

    /**
     * 画网格
     * @param canvas
     */
    private void drawLine(Canvas canvas){
        Path path = new Path();
        //网格线之间的间距
        float distance =  mRadius / (mCount-1);
        for (int i = 0; i < mCount; i++){//外面的网格图形
            float currentRadius = i * distance;//当前半径
            if (i == mCount -1){
                //存储最后一圈网格的点的坐标
                mLastPoints.add(new LastPoint(currentRadius,0));
                mLastPoints.add(new LastPoint(currentRadius/2,-currentRadius));
                mLastPoints.add(new LastPoint(-currentRadius/2,-currentRadius));
                mLastPoints.add(new LastPoint(-currentRadius,0));
                mLastPoints.add(new LastPoint(-currentRadius/2,currentRadius));
                mLastPoints.add(new LastPoint(currentRadius/2,currentRadius));
            }
            //6个点坐标组成一个网格图形
            path.lineTo(currentRadius,0);
            //设置上一次操作的坐标点
            path.moveTo(currentRadius,0);
            path.lineTo(currentRadius/2,-currentRadius);
            path.lineTo(-currentRadius/2,-currentRadius);
            path.lineTo(-currentRadius,0);
            path.lineTo(-currentRadius/2,currentRadius);
            path.lineTo(currentRadius/2,currentRadius);
            path.close();
            canvas.drawPath(path,mLinePaint);
        }
    }

技术分享

绘制从中心到末端的直线

    /**
     * 画网格对角线
     * @param canvas
     */
    private void drawGridLine(Canvas canvas){
        Path path = new Path();
        for (int i = 0; i < mLastPoints.size(); i++){
            path.reset();
            LastPoint point = mLastPoints.get(i);
            float x = point.x;
            float y = point.y;
            path.lineTo(x, y);
            canvas.drawPath(path, mLinePaint);
        }
    }

技术分享

绘制末端文本

由于文本与末端有一定的距离,所以需要加上一定的偏移量;当文本在网格左边显示的时候,会与网格有重叠,所以需要先计算文本长度,然后再向左边偏移对应的距离,这样就可以解决重叠问题。

    /**
     * 画文本
     * @param canvas
     */
    private void drawText(Canvas canvas){
        for (int i = 0; i < mLastPoints.size(); i++){
            //文本长度
            float dis = mTextPaint.measureText(mTitles[i]);

            LastPoint point = mLastPoints.get(i);
            float x = point.x;
            float y = point.y;
            if (i == 2 || i == 3 || i == 4){
                //左边绘制文本:文本显示在坐标左边
                x = x - dis;
            }
            if (y > 0){
                y+=18;
            }
            canvas.drawText(mTitles[i],x,y,mTextPaint);
        }
    }

技术分享

绘制填充区域

    /**
     * 画数据线:填充区域
     * @param canvas
     */
    private void drawDataLine(Canvas canvas){
        if (mDataPoints == null || mDataPoints.size() == 0)
            return;
        Path path = new Path();
        for (int i = 0; i < mDataPoints.size(); i++){
            LastPoint point = mDataPoints.get(i);
            float x = point.x;
            float y = point.y;
            path.lineTo(x, y);
            if (i == 0){//将上一次操作点移到第一个点坐标,保证最后调用close,形成一个封闭的形状
                path.moveTo(x,y);
            }
            mValuePaint.setAlpha(255);
            //画小圆点
            canvas.drawCircle(x,y,8,mValuePaint);
        }
        path.close();
        mValuePaint.setAlpha(127);
        canvas.drawPath(path, mValuePaint);

    }

技术分享

 

Android雷达图(蜘蛛网图)

标签:highlight   测量   mda   val   构造   效果图   方式   []   ext   

原文地址:http://www.cnblogs.com/hacjy/p/7372741.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!