安卓开发雷达图

项目中有图表的绘制 折线图,k线图,柱状图跟雷达图

今天就写一写如何实现自定义view来实现雷达图效果

1.设置变量

private int count = 6;                //数据个数  
    private float angle = (float) (Math.PI*2/count);     
    private float radius;                   //网格最大半径  
    private int centerX;                  //中心X  
    private int centerY;                  //中心Y  
    private String[] titles = {"a","b","c","d","e","f"};  //各维度标签
//    private double[] data = {3,3,3,3,3,3}; //各维度分值
    private ArrayList<Float> data = new ArrayList<Float>();  //各维度值
    private float maxValue = 5;             //数据最大值
    private Paint mainPaint;                //雷达区画笔  
    private Paint innerValuePaint;               //数据区画笔
    private Paint textPaint;                //文本画笔
    private Paint outerValuePaint;                //雷达区边框画笔
    private float circleRadius = 2;                //圆点半径
    private int lableCount = 6;                //Y轴值个数
    private int innerAlpha = 166;                //蜘蛛网局部透明度
    private float strokeWidth = 2;                //蜘蛛网边框宽度
    private boolean drawLabels = false;                //绘制轴值
    private boolean showValueText = false;                //是否显示轴上的值
    private float circleZero =(float) Math.PI/2;    ;                //初始角度为90度


2.初始化画笔

 private void init() {
        count = titles.length;
       
        mainPaint = new Paint();
        mainPaint.setAntiAlias(true);
        mainPaint.setColor(Color.GRAY);
        mainPaint.setStyle(Paint.Style.STROKE);

        innerValuePaint = new Paint();
        innerValuePaint.setAntiAlias(true);
        innerValuePaint.setColor(Color.BLUE);
        innerValuePaint.setStyle(Paint.Style.FILL);
        outerValuePaint = new Paint();
        outerValuePaint.setAntiAlias(true);
        outerValuePaint.setColor(Color.BLUE);
        outerValuePaint.setStyle(Paint.Style.STROKE);

        textPaint = new Paint();
        textPaint.setTextSize(14);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(Color.BLACK);
    }


 

3.设置雷达图大小(设置雷达半径)

 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        radius = Math.min(h, w)/2*0.8f;
        centerX = w/2;
        centerY = h/2;
        postInvalidate();
        super.onSizeChanged(w, h, oldw, oldh);
    }


4.绘制正多边形

/**
     * 绘制正多边形
     */
    private void drawPolygon(Canvas canvas){
        Path path = new Path();
        float r = radius/(lableCount-1);
        for(int i=1;i<lableCount;i++){
            float curR = r*i;
            path.reset();
            for(int j=0;j<count;j++){
                if(j==0){
                    path.moveTo(centerX,centerY-curR);
                    if(drawLabels){
                        String text =String.valueOf(Float.valueOf((maxValue/(lableCount-1))*i));
                        float dis = textPaint.measureText(text);//文本长度
                        canvas.drawText(text,centerX,centerY-curR,textPaint);
                    }
                }else{
                    float x = (float) (centerX+curR*Math.cos(angle*j-circleZero));
                    float y = (float) (centerY+curR*Math.sin(angle*j-circleZero));
                    path.lineTo(x,y);
                }
            }
            path.close();
            canvas.drawPath(path, mainPaint);
        }
    }
    


3.绘制直线

/**
     * 绘制直线
     */
    private void drawLines(Canvas canvas){
        Path path = new Path();
        for(int i=0;i<count;i++){
            path.reset();
            path.moveTo(centerX, centerY);
            float x = (float) (centerX+radius*Math.cos(angle*i-circleZero));
            float y = (float) (centerY+radius*Math.sin(angle*i-circleZero));
            path.lineTo(x, y);
            canvas.drawPath(path, mainPaint);
        }
    }


6.绘制标签文字

/**
     * 绘制文字
     * @param canvas
     */
    private void drawText(Canvas canvas){
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        float fontHeight = fontMetrics.descent - fontMetrics.ascent;
        for(int i=0;i<count;i++){
            float x = (float) (centerX+(radius+fontHeight/2)*Math.cos(angle*i-circleZero));
            float y = (float) (centerY+(radius+fontHeight/2)*Math.sin(angle*i-circleZero));
            float dis = textPaint.measureText(titles[i]);//文本长度
            if(i < count/2 &&  i > 0 ){//第12象限
                canvas.drawText(titles[i], x,y,textPaint);
            }else if(i > count/2){//第34象限
                canvas.drawText(titles[i], x-dis,y,textPaint);
            }else if(i == 0){
                canvas.drawText(titles[i], x-dis/2,y,textPaint);
            }else if(i == count/2){
                canvas.drawText(titles[i], x-dis/2,y+15,textPaint);
            }
        }
    }


7.设置雷达区域

/**
     * 绘制区域
     * @param canvas
     */
    private void drawRegion(Canvas canvas){
        Path path = new Path();
        innerValuePaint.setAlpha(255);
        float x0 = centerX,y0 = centerY;
        for(int i=0;i<count;i++){
            double percent = data.get(i)/maxValue;
            float x = (float) (centerX+radius*Math.cos(angle*i-circleZero)*percent);
            float y = (float) (centerY+radius*Math.sin(angle*i-circleZero)*percent);
            if(i==0){
                path.moveTo(centerX, y);
                x0 = x;
                y0 = y;
            }else {
                path.lineTo(x,y);
            }
            if(i == count-1){
                path.lineTo(x0,y0);
            }
            //绘制小圆点
            canvas.drawCircle(x,y,circleRadius,outerValuePaint);
            if(showValueText){
                float dis = textPaint.measureText(String.valueOf(data.get(i)));//文本长度
                if(i < count/2 &&  i > 0 ){//第12象限
                    canvas.drawText(String.valueOf(data.get(i)), x,y,textPaint);
                }else if(i > count/2){//第34象限
                    canvas.drawText(String.valueOf(data.get(i)), x-dis,y,textPaint);
                }else if(i == 0){
                    canvas.drawText(String.valueOf(data.get(i)), x-dis/2,y,textPaint);
                }else if(i == count/2){
                    canvas.drawText(String.valueOf(data.get(i)), x-dis/2,y+15,textPaint);
                }
            }
        }
        innerValuePaint.setAlpha(innerAlpha);
        canvas.drawPath(path, innerValuePaint);
        //绘制填充区域
        outerValuePaint.setAlpha(255);
        outerValuePaint.setStrokeWidth(strokeWidth);
        canvas.drawPath(path, outerValuePaint);
    }


完整代码如下:

package com.zhuhao.finance.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

import java.util.ArrayList;

/**
 * Created by gaoli on 2017/7/12.
 */
public class RadarView extends View {
    private int count = 6;                //数据个数  
    private float angle = (float) (Math.PI*2/count);     
    private float radius;                   //网格最大半径  
    private int centerX;                  //中心X  
    private int centerY;                  //中心Y  
    private String[] titles = {"a","b","c","d","e","f"};  //各维度标签
//    private double[] data = {3,3,3,3,3,3}; //各维度分值
    private ArrayList<Float> data = new ArrayList<Float>();  //各维度值
    private float maxValue = 5;             //数据最大值
    private Paint mainPaint;                //雷达区画笔  
    private Paint innerValuePaint;               //数据区画笔
    private Paint textPaint;                //文本画笔
    private Paint outerValuePaint;                //雷达区边框画笔
    private float circleRadius = 2;                //圆点半径
    private int lableCount = 6;                //Y轴值个数
    private int innerAlpha = 166;                //蜘蛛网局部透明度
    private float strokeWidth = 2;                //蜘蛛网边框宽度
    private boolean drawLabels = false;                //绘制轴值
    private boolean showValueText = false;                //是否显示轴上的值
    private float circleZero =(float) Math.PI/2;    ;                //初始角度为90度


    public void setCircleRadius(float circleRadius) {
        this.circleRadius = circleRadius;
    }

    
    public RadarView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    
    public RadarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    public RadarView(Context context) {
        super(context);
        init();
    }
    
    
    //初始化  
    private void init() {
        count = titles.length;
       
        mainPaint = new Paint();
        mainPaint.setAntiAlias(true);
        mainPaint.setColor(Color.GRAY);
        mainPaint.setStyle(Paint.Style.STROKE);

        innerValuePaint = new Paint();
        innerValuePaint.setAntiAlias(true);
        innerValuePaint.setColor(Color.BLUE);
        innerValuePaint.setStyle(Paint.Style.FILL);
        outerValuePaint = new Paint();
        outerValuePaint.setAntiAlias(true);
        outerValuePaint.setColor(Color.BLUE);
        outerValuePaint.setStyle(Paint.Style.STROKE);

        textPaint = new Paint();
        textPaint.setTextSize(14);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setColor(Color.BLACK);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        radius = Math.min(h, w)/2*0.8f;
        centerX = w/2;
        centerY = h/2;
        postInvalidate();
        super.onSizeChanged(w, h, oldw, oldh);
    }

    

    @Override
    protected void onDraw(Canvas canvas) {
        drawPolygon(canvas);
        drawLines(canvas);
        drawText(canvas);
        drawRegion(canvas);
    }

    /**
     * 绘制正多边形
     */
    private void drawPolygon(Canvas canvas){
        Path path = new Path();
        float r = radius/(lableCount-1);
        for(int i=1;i<lableCount;i++){
            float curR = r*i;
            path.reset();
            for(int j=0;j<count;j++){
                if(j==0){
                    path.moveTo(centerX,centerY-curR);
                    if(drawLabels){
                        String text =String.valueOf(Float.valueOf((maxValue/(lableCount-1))*i));
                        float dis = textPaint.measureText(text);//文本长度
                        canvas.drawText(text,centerX,centerY-curR,textPaint);
                    }
                }else{
                    float x = (float) (centerX+curR*Math.cos(angle*j-circleZero));
                    float y = (float) (centerY+curR*Math.sin(angle*j-circleZero));
                    path.lineTo(x,y);
                }
            }
            path.close();
            canvas.drawPath(path, mainPaint);
        }
    }
    
    /**
     * 绘制直线
     */
    private void drawLines(Canvas canvas){
        Path path = new Path();
        for(int i=0;i<count;i++){
            path.reset();
            path.moveTo(centerX, centerY);
            float x = (float) (centerX+radius*Math.cos(angle*i-circleZero));
            float y = (float) (centerY+radius*Math.sin(angle*i-circleZero));
            path.lineTo(x, y);
            canvas.drawPath(path, mainPaint);
        }
    }

    /**
     * 绘制文字
     * @param canvas
     */
    private void drawText(Canvas canvas){
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        float fontHeight = fontMetrics.descent - fontMetrics.ascent;
        for(int i=0;i<count;i++){
            float x = (float) (centerX+(radius+fontHeight/2)*Math.cos(angle*i-circleZero));
            float y = (float) (centerY+(radius+fontHeight/2)*Math.sin(angle*i-circleZero));
            float dis = textPaint.measureText(titles[i]);//文本长度
            if(i < count/2 &&  i > 0 ){//第12象限
                canvas.drawText(titles[i], x,y,textPaint);
            }else if(i > count/2){//第34象限
                canvas.drawText(titles[i], x-dis,y,textPaint);
            }else if(i == 0){
                canvas.drawText(titles[i], x-dis/2,y,textPaint);
            }else if(i == count/2){
                canvas.drawText(titles[i], x-dis/2,y+15,textPaint);
            }
        }
    }

    /**
     * 绘制区域
     * @param canvas
     */
    private void drawRegion(Canvas canvas){
        Path path = new Path();
        innerValuePaint.setAlpha(255);
        float x0 = centerX,y0 = centerY;
        for(int i=0;i<count;i++){
            double percent = data.get(i)/maxValue;
            float x = (float) (centerX+radius*Math.cos(angle*i-circleZero)*percent);
            float y = (float) (centerY+radius*Math.sin(angle*i-circleZero)*percent);
            if(i==0){
                path.moveTo(centerX, y);
                x0 = x;
                y0 = y;
            }else {
                path.lineTo(x,y);
            }
            if(i == count-1){
                path.lineTo(x0,y0);
            }
            //绘制小圆点
            canvas.drawCircle(x,y,circleRadius,outerValuePaint);
            if(showValueText){
                float dis = textPaint.measureText(String.valueOf(data.get(i)));//文本长度
                if(i < count/2 &&  i > 0 ){//第12象限
                    canvas.drawText(String.valueOf(data.get(i)), x,y,textPaint);
                }else if(i > count/2){//第34象限
                    canvas.drawText(String.valueOf(data.get(i)), x-dis,y,textPaint);
                }else if(i == 0){
                    canvas.drawText(String.valueOf(data.get(i)), x-dis/2,y,textPaint);
                }else if(i == count/2){
                    canvas.drawText(String.valueOf(data.get(i)), x-dis/2,y+15,textPaint);
                }
            }
        }
        innerValuePaint.setAlpha(innerAlpha);
        canvas.drawPath(path, innerValuePaint);
        //绘制填充区域
        outerValuePaint.setAlpha(255);
        outerValuePaint.setStrokeWidth(strokeWidth);
        canvas.drawPath(path, outerValuePaint);
    }
    
    //设置标题
    public void setTitles(String[] titles) {
        this.titles = titles;
    }

    //设置数值
    public void setData(ArrayList<Float> data) {
        this.data = data;
    }

    
    public float getMaxValue() {
        return maxValue;
    }

    //设置最大数值
    public void setMaxValue(float maxValue) {
        this.maxValue = maxValue;
    }
    
    //设置蜘蛛网颜色
    public void setMainPaintColor(int color){
        mainPaint.setColor(color);
    }
    //设置蜘蛛网透明度
    public void setMainPaintAlpha(int alpha){
        mainPaint.setAlpha(alpha);
    }
    //设置蜘蛛网区域内透明度
    public void setValuePaintAlpha(int alpha){
        innerValuePaint.setAlpha(alpha);
    }

    //设置标题颜色
    public void setTextPaintColor(int color){
        textPaint.setColor(color);
    }

    //设置覆盖局域颜色
    public void setValuePaintColor(int color){
        innerValuePaint.setColor(color);
        outerValuePaint.setColor(color);
    }

    //设置字体大小
    public void setTextPaintTextSize(float size){
        textPaint.setTextSize(size);
    }

    public void setLableCount(int lableCount) {
        this.lableCount = lableCount;
    }

    public void setInnerAlpha(int innerAlpha) {
        this.innerAlpha = innerAlpha;
    }

    public void setStrokeWidth(float strokeWidth) {
        this.strokeWidth = strokeWidth;
    }

    public void setDrawLabels(boolean drawLabels) {
        this.drawLabels = drawLabels;
    }

    public void setShowValueText(boolean showValueText) {
        this.showValueText = showValueText;
    }
}


activity中

@BindView(R.id.rate_chart_radar)
    RadarView mChart;

private void initRadar() {
        String[] mActivities = new String[]{"商业模式", "核心壁垒", "团队结构", "运营管理", "盈利能力","成长能力"};
        mChart.setTitles(mActivities);
        ArrayList<Float> data = new ArrayList<>();
        data.add(1.5f);
        data.add(4f);
        data.add(3.8f);
        data.add(2.2f);
        data.add(3.0f);
        data.add(4.5f);
        mChart.setData(data);
        mChart.setMaxValue(5);
        mChart.setValuePaintColor(Color.rgb(239,83,80));
        mChart.setStrokeWidth(3f);
        mChart.setMainPaintColor(Color.GRAY);
        mChart.setCircleRadius(1f);
        mChart.setTextPaintTextSize(28);
        mChart.setInnerAlpha(166);
        mChart.setLableCount(6);
        mChart.setDrawLabels(false);
        mChart.setShowValueText(true);
        mChart.invalidate();
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫叶思念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值