Android 雷达图

效果如下图


自定义View代码


1.数据源

/**
 * Created by fengzhiqi on 2017/6/10.
 */

public class RadarData {

    private String title;
    private double percentage;


    public RadarData(String title, double percentage) {
        this.title = title;
        this.percentage = percentage;
    }


    public String getTitle() {
        return title;
    }


    public double getPercentage() {
        return percentage;
    }
}

/**
 * Created by fengzhiqi on 2017/6/10.
 */
public class RadarView extends View {


private final static String TAG = RadarView.class.getSimpleName();


   private List<RadarData> dataList;


   private int count = 6;//雷达网圈数
   private float angle;//多边形弧度
   private float radius;
   private float maxValue = 100f;
   private Paint mainPaint;//雷达区画笔
   private Paint valuePaint;//数据区画笔
   private Paint textPaint;//文本画笔


   private int mainColor = 0xFF888888;//雷达区颜色
   private int valueColor = 0xFF79D4FD;//数据区颜色
   private int textColor = 0xFF808080;//文本颜色


   private float mainLineWidth = 1f;//雷达网线宽度dp
   private float valueLineWidth = 1f;//数据区边宽度dp
   private float valuePointRadius = 2f;//数据区圆点半径dp
   private float textSize = 16f;//字体大小sp


   private int mWidth, mHeight;


   public RadarView(Context context) {
       this(context, null);
   }


   public RadarView(Context context, AttributeSet attrs) {
       this(context, attrs, 0);
   }


   public RadarView(Context context, AttributeSet attrs, int defStyleAttr) {
       super(context, attrs, defStyleAttr);


       setup();
   }


   private void setup() {
       mainPaint = new Paint();
       mainPaint.setAntiAlias(true);
       mainPaint.setColor(mainColor);
       mainPaint.setStyle(Paint.Style.STROKE);


       valuePaint = new Paint();
       valuePaint.setAntiAlias(true);
       valuePaint.setColor(valueColor);
       valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);


       textPaint = new Paint();
       textPaint.setAntiAlias(true);
       textPaint.setStyle(Paint.Style.FILL);
       textPaint.setColor(textColor);
   }


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


   @Override
   protected void onDraw(Canvas canvas) {
       canvas.translate(mWidth / 2, mHeight / 2);


       if (isDataListValid()) {
           drawSpiderweb(canvas);
           drawText(canvas);
           drawRegion(canvas);
       }
   }


   /**
    * 绘制蜘蛛网
    *
    * @param canvas
    */
   private void drawSpiderweb(Canvas canvas) {
       mainPaint.setStrokeWidth(dip2px(getContext(), mainLineWidth));
       Path webPath = new Path();
       Path linePath = new Path();
       float r = radius / (count - 1);//蜘蛛丝之间的间距
       for (int i = 0; i < count; i++) {
           float curR = r * i;//当前半径
           webPath.reset();
           for (int j = 0; j < count; j++) {
               float x = (float) (curR * Math.sin(angle / 2 + angle * j));
               float y = (float) (curR * Math.cos(angle / 2 + angle * j));
               if (j == 0) {
                   webPath.moveTo(x, y);
               } else {
                   webPath.lineTo(x, y);
               }
               if (i == count - 1) {//当绘制最后一环时绘制连接线
                   linePath.reset();
                   linePath.moveTo(0, 0);
                   linePath.lineTo(x, y);
                   canvas.drawPath(linePath, mainPaint);
               }
           }
           webPath.close();
           canvas.drawPath(webPath, mainPaint);
       }
   }


   /**
    * 绘制文本
    *
    * @param canvas
    */
   private void drawText(Canvas canvas) {
       textPaint.setTextSize(sp2px(getContext(), textSize));
       Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
       float fontHeight = fontMetrics.descent - fontMetrics.ascent;
       for (int i = 0; i < count; i++) {
           float x = (float) ((radius + fontHeight * 2) * Math.sin(angle / 2 + angle * i));
           float y = (float) ((radius + fontHeight * 2) * Math.cos(angle / 2 + angle * i));
           String title = dataList.get(i).getTitle();
           float dis = textPaint.measureText(title);//文本长度
           canvas.drawText(title, x - dis / 2, y, textPaint);
       }
   }


   /**
    * 绘制区域
    *
    * @param canvas
    */
   private void drawRegion(Canvas canvas) {
       valuePaint.setStrokeWidth(dip2px(getContext(), valueLineWidth));
       Path path = new Path();
       valuePaint.setAlpha(255);
       path.reset();


       for (int i = 0; i < count; i++) {
           double percent = dataList.get(i).getPercentage() / maxValue;
           float x = (float) (radius * Math.sin(angle / 2 + angle * i) * percent);
           float y = (float) (radius * Math.cos(angle / 2 + angle * i) * percent);
           if (i == 0) {
               path.moveTo(x, y);
           } else {
               path.lineTo(x, y);
           }
           //绘制小圆点
           canvas.drawCircle(x, y, dip2px(getContext(), valuePointRadius), valuePaint);
       }
       path.close();
       valuePaint.setStyle(Paint.Style.STROKE);
       canvas.drawPath(path, valuePaint);
       valuePaint.setAlpha(128);
       //绘制填充区域
       valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);
       canvas.drawPath(path, valuePaint);
   }




   private boolean isDataListValid() {
       return dataList != null && dataList.size() >= 3;
   }




   public void setDataList(List<RadarData> dataList) {
       if (isDataListValid()) {
           throw new RuntimeException("The number of data can not be less than 3");
       } else {
           this.dataList = dataList;
           count = dataList.size();//圈数等于数据个数,默认为6
           angle = (float) (Math.PI * 2 / count);
           invalidate();
       }
   }




   public static int dip2px(Context context, float dipValue) {
       final float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dipValue * scale + 0.5f);
   }


   public static int sp2px(Context context, float spValue) {
       final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
       return (int) (spValue * fontScale + 0.5f);
   }

}








使用方法:

非常简单


布局

<com.example.radarviewdemo.RadarView
        android:id="@+id/radarView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

使用

1.创建数据源

2.绑定数据

RadarView radarView = (RadarView) findViewById(R.id.radarView);
   //存放数据的
       List<RadarData> dataList = new ArrayList<RadarData>();
       for (int i = 1; i < 1; i++) {
       //第一个值为每项名称
       //第二个值是百分之多少
        RadarData data = new RadarData("标题" + i,10*i);
        dataList.add(data);
       }        
       radarView.setDataList(dataList);


猜你喜欢

转载自blog.csdn.net/fengzhiqi1993/article/details/73000252