package com.example.kotlintest;

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

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

public class RadarChartView extends View {
    private List<DimensionBean> dimensionList;
    private Paint linePaint;
    private Paint shadowPaint;
    private Paint pointPaint;
    //里面放放射线的path
    private List<PathMeasure> pathMeasureList;
    //放射线的path
    private List<Path> pathList;
    //    放放射线与环线交叉点的位置
    private List<List<float[]>> intersectionList;
    //    每个放射线配置一个matrix
    private List<Matrix> matrixList;
    //    有几个刻度
    private int scale;
    //    每个刻度都有环线
    private List<Path> loopPathList;
    //    放射线刻度最大值
    private float maxValue;
    //    链接放射线上的刻度的path
    private Path valuePath;
    //    链接放射线上的刻度的点
    private List<float[]> valueList;
//    原点的半径
    private int circleWidth;
//  确定绘制文字的地方

    public RadarChartView(Context context) {
        super(context);
        initView();
    }

    public RadarChartView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public RadarChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    public RadarChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initView();
    }

    private void initView() {
        linePaint = new Paint();
        linePaint.setColor(Color.BLACK);
        linePaint.setStrokeWidth(UIUtils.dp2px(getContext(), 1));
        linePaint.setAntiAlias(true);
        linePaint.setStyle(Paint.Style.STROKE);

        pointPaint = new Paint();
        pointPaint.setAntiAlias(true);
        pointPaint.setColor(Color.parseColor("#3bFB725B"));

        shadowPaint = new Paint();
        shadowPaint.setStyle(Paint.Style.FILL);
        shadowPaint.setAntiAlias(true);
        shadowPaint.setColor(Color.parseColor("#3b00ff00"));

        pathMeasureList = new ArrayList<>();
        pathList = new ArrayList<>();
        intersectionList = new ArrayList<>();
        matrixList = new ArrayList<>();

        loopPathList = new ArrayList<>();
        valuePath = new Path();
        valueList = new ArrayList<>();
        circleWidth = UIUtils.dp2px(getContext(),4);
    }

    @Override
    protected void onDraw(@NonNull Canvas canvas) {
        super.onDraw(canvas);
        for (int i = 0; i < dimensionList.size(); i++) {
            pathList.get(i).moveTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
            pathList.get(i).lineTo(getMeasuredWidth() / 2, getMeasuredHeight() / 2 - UIUtils.dp2px(getContext(), 65));
            pathMeasureList.get(i).setPath(pathList.get(i), false);
            canvas.drawPath(pathList.get(i), linePaint);
            pathMeasureList.get(i).getMatrix(pathMeasureList.get(i).getLength(), matrixList.get(i), PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);
//           注意,这里不要使用preRotate和postRotate,因为坐标会乱得离谱
            matrixList.get(i).setRotate(360 / dimensionList.size() * i, getMeasuredWidth() / 2, getMeasuredHeight() / 2);
            pathList.get(i).transform(matrixList.get(i));
            pathMeasureList.get(i).setPath(pathList.get(i), false);
            canvas.drawPath(pathList.get(i), linePaint);
        }
        for (int j = 0; j < scale; j++) {
            for (int i = 0; i < pathMeasureList.size(); i++) {
                pathMeasureList.get(i).getPosTan(pathMeasureList.get(i).getLength() / scale * (j + 1), intersectionList.get(j).get(i), null);
            }
        }
        for (int i = 0; i < intersectionList.size(); i++) {
            for (int j = 0; j < intersectionList.get(i).size(); j++) {
                float[] array = intersectionList.get(i).get(j);
                if (j == 0) {
                    loopPathList.get(i).moveTo(array[0], array[1]);
                } else {
                    loopPathList.get(i).lineTo(array[0], array[1]);
                }
            }
            loopPathList.get(i).close();
            canvas.drawPath(loopPathList.get(i), linePaint);
        }
        for (int i = 0; i < dimensionList.size(); i++) {
            pathMeasureList.get(i).getPosTan(pathMeasureList.get(i).getLength()/100*dimensionList.get(i).getValue(),valueList.get(i),null);
        }
        for (int i = 0; i < valueList.size(); i++) {
            if(i==0){
                valuePath.moveTo(valueList.get(i)[0],valueList.get(i)[1]);
            }else{
                valuePath.lineTo(valueList.get(i)[0],valueList.get(i)[1]);
            }
            canvas.drawCircle(valueList.get(i)[0],valueList.get(i)[1],circleWidth,pointPaint);
        }
        canvas.drawPath(valuePath,shadowPaint);

    }

    public void setDimensionList(List<DimensionBean> dimensionList, int scale, float maxValue) {
        this.scale = scale;
        this.maxValue = maxValue;
        this.dimensionList = dimensionList;
        for (int i = 0; i < dimensionList.size(); i++) {
            pathMeasureList.add(new PathMeasure());
            pathList.add(new Path());
            float[] valueFloat = new float[2];
            valueList.add(valueFloat);
            matrixList.add(new Matrix());
            loopPathList.add(new Path());
        }
        for (int i = 0; i < scale; i++) {
            List<float[]> loopPositionList = new ArrayList<>();
            for (int j = 0; j < dimensionList.size(); j++) {
                float[] floatArray = new float[2];
                loopPositionList.add(floatArray);
            }
            intersectionList.add(loopPositionList);
        }
        invalidate();
    }
}

Activity中调用

package com.example.kotlintest

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import androidx.viewpager2.widget.ViewPager2

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var radarChartView = findViewById<RadarChartView>(R.id.radarView)
        var dimensionList = mutableListOf<DimensionBean>()
        dimensionList.add(DimensionBean(19,"进攻[19]"))
        dimensionList.add(DimensionBean(39,"技术[39]"))
        dimensionList.add(DimensionBean(59,"战术[59]"))
        dimensionList.add(DimensionBean(49,"防守[49]"))
        dimensionList.add(DimensionBean(99,"创造力[99]"))
        radarChartView.setDimensionList(dimensionList,4,100f)
    }
}
package com.example.kotlintest;

public class DimensionBean {
    private int value;
    private String show;

    public DimensionBean(int value, String show) {
        this.value = value;
        this.show = show;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public String getShow() {
        return show;
    }

    public void setShow(String show) {
        this.show = show;
    }
}

王学岗绘制雷达图-LMLPHP

11-17 17:20