LOL英雄战力效果【五星战力分析】5星

大概效果这样 

LOL英雄战力效果【五星战力分析】5星_第1张图片


代码如下:

/**
 * Create by Mazhanzhu on 2020/10/12
 * LOL英雄战斗力效果
 */
public class LOLview extends View {
    public static final String TAG = "LOLview";
    private int n;    //边的数量或者能力的个数
    private float R;    //最外圈的半径,顶点到中心点的距离
    private int intervalCount; //间隔数量,就把半径分为几段
    private float angle;     //两条顶点到中线点的线之间的角度
    private Paint linePaint;  //画线的笔
    private Paint textPaint;  //画文字的笔
    private int viewHeight;   //控件宽度
    private int viewWidth;    //控件高度
    private ArrayList data = new ArrayList<>();  //元数据
    private ArrayList> pointsArrayList = new ArrayList<>();  //存储多边形顶点数组的数组
    private ArrayList abilityPoints = new ArrayList<>();   //存储能力点的数组

    public LOLview(Context context) {
        //这地方改为this,使得不管怎么初始化都会进入第三个构造函数中
        this(context, null);
    }

    public LOLview(Context context, @Nullable AttributeSet attrs) {
        //这地方改为this,使得不管怎么初始化都会进入第三个构造函数中
        this(context, attrs, 0);
    }

    public LOLview(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initSize(context);

        initPaint(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //设置控件的最终视图大小(宽高)
        setMeasuredDimension(viewWidth, viewHeight);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        initSize(getContext());
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (data.size() > 0) {
            //把画布的原点移动到控件的中心点
            canvas.translate(viewWidth / 2, viewHeight / 2);
            //绘制多边形边,每一圈都绘制
            drawPolygon(canvas);
            /**
             * 画轮廓线
             * 1.先画最外面的多边形轮廓
             * 2.再画顶点到中心的线
             */
            drawOutLine(canvas);
            //画能力线
            drawAbilityLine(canvas);
            //画能力描述的文字
            drawAbilityText(canvas);
        }
    }

    private void drawAbilityText(Canvas canvas) {
        canvas.save();
        //先计算出坐标来
        ArrayList textPoints = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            float r = R + PxUtils.dp2pxF(getContext(), 15f);
            float x = (float) (r * Math.cos(i * angle - Math.PI / 2));
            float y = (float) (r * Math.sin(i * angle - Math.PI / 2));
            textPoints.add(new PointF(x, y));
        }
        //拿到字体测量器
        Paint.FontMetrics metrics = textPaint.getFontMetrics();
        for (int i = 0; i < data.size(); i++) {
            float x = textPoints.get(i).x;
            //ascent:上坡度,是文字的基线到文字的最高处的距离
            //descent:下坡度,,文字的基线到文字的最低处的距离
            float y = textPoints.get(i).y - (metrics.ascent + metrics.descent) / 2;
            canvas.drawText(data.get(i).name, x, y, textPaint);
        }

        canvas.restore();
    }

    private void drawAbilityLine(Canvas canvas) {
        canvas.save();

        //先把能力点初始化出来
        abilityPoints = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            float r = R * (data.get(i).num / 100.0f);  //能力值/100再乘以半径就是所占的比例
            float x = (float) (r * Math.cos(i * angle - Math.PI / 2));
            float y = (float) (r * Math.sin(i * angle - Math.PI / 2));
            abilityPoints.add(new PointF(x, y));
        }

        linePaint.setStrokeWidth(PxUtils.dp2px(getContext(), 2f));
//        linePaint.setColor(Color.parseColor("#E96153"));
        linePaint.setColor(Color.parseColor("#A67EA4E3"));
//        linePaint.setStyle(Paint.Style.STROKE);  //设置空心的
        linePaint.setStyle(Paint.Style.FILL);  //设置实心的

        Path path = new Path();  //路径
        for (int i = 0; i < data.size(); i++) {
            float x = abilityPoints.get(i).x;
            float y = abilityPoints.get(i).y;
            if (i == 0) {
                path.moveTo(x, y);
            } else {
                path.lineTo(x, y);
            }
        }
        path.close();   //别忘了闭合

        canvas.drawPath(path, linePaint);

        canvas.restore();
    }

    private void drawOutLine(Canvas canvas) {
        canvas.save();//保存画布当前状态(平移、放缩、旋转、裁剪等),和canvas.restore()配合使用

        linePaint.setColor(Color.parseColor("#eef2fb"));
        linePaint.setStyle(Paint.Style.STROKE);  //设置空心的

        //先画最外面的多边形轮廓
        Path path = new Path();  //路径
        for (int i = 0; i < data.size(); i++) {
            //只需要第一组的点
            float x = pointsArrayList.get(0).get(i).x;
            float y = pointsArrayList.get(0).get(i).y;
            if (i == 0) {
                //如果是第一个点就把path的起点设置为这个点
                path.moveTo(x, y);
            } else {
                path.lineTo(x, y);
            }
        }
        path.close(); //闭合路径
        canvas.drawPath(path, linePaint);

        //再画顶点到中心的线
        for (int i = 0; i < data.size(); i++) {
            float x = pointsArrayList.get(0).get(i).x;
            float y = pointsArrayList.get(0).get(i).y;
            canvas.drawLine(0, 0, x, y, linePaint); //起点都是中心点
        }
        canvas.restore();
    }

    private void drawPolygon(Canvas canvas) {
        canvas.save();//保存画布当前状态(平移、放缩、旋转、裁剪等),和canvas.restore()配合使用

        linePaint.setStyle(Paint.Style.FILL_AND_STROKE);  //设置为填充且描边

        Path path = new Path();  //路径
        for (int i = 0; i < intervalCount; i++) {  //循环、一层一层的绘制
            //每一层的颜色都都不同
            switch (i) {
                case 0:
                    linePaint.setColor(Color.parseColor("#eef2fb"));
                    break;
                case 1:
                    linePaint.setColor(Color.parseColor("#dfe6f9"));
                    break;
                case 2:
                    linePaint.setColor(Color.parseColor("#ccdaf5"));
                    break;
                case 3:
                    linePaint.setColor(Color.parseColor("#b8c9f5"));
                    break;
            }
            for (int j = 0; j < data.size(); j++) {   //每一层有n个点
                float x = pointsArrayList.get(i).get(j).x;
                float y = pointsArrayList.get(i).get(j).y;
                if (j == 0) {
                    //如果是每层的第一个点就把path的起点设置为这个点
                    path.moveTo(x, y);
                } else {
                    path.lineTo(x, y);
                }
            }
            path.close();  //设置为闭合的
            canvas.drawPath(path, linePaint);
            path.reset();   //清除path存储的路径
        }
        canvas.restore();
    }

    /**
     * 初始化一些固定数据
     *
     * @param context
     */
    private void initSize(Context context) {
//        R = dp2pxF(context, 100);  //半径暂时设为100dp
        intervalCount = 4;   //有四层
        angle = (float) ((2 * Math.PI) / data.size());     //一周是2π,这里用π,因为进制的问题,不能用360度,画出来会有问题

        //拿到屏幕的宽高,单位是像素
        int screenWidth = PxUtils.getScreenWidth(context) - PxUtils.dp2px(52);
        //控件设置为正方向
        viewWidth = screenWidth;
        viewHeight = screenWidth / 3 * 2;

        R = viewWidth / 4;  //半径设为宽度的三分之一
    }

    /**
     * 初始化画笔
     */
    private void initPaint(Context context) {
        //画线的笔
        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //设置线宽度
        linePaint.setStrokeWidth(PxUtils.dp2px(context, 1f));

        //画文字的笔
        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.CENTER);  //设置文字居中
        textPaint.setColor(Color.BLACK);
        textPaint.setTextSize(PxUtils.sp2pxF(context, 14f));
    }

    /**
     * 传入元数据
     */
    public void setData(ArrayList list, Context context) {
        if (list.size() == 0) {
            return;
        }
        data = list;
        initSize(context);
        initPoints();
        //View本身调用迫使view重画
        invalidate();
    }

    /**
     * 初始化多边形的所有点 每一圈7个点,有4圈
     */
    private void initPoints() {
        float x;
        float y;
        for (int i = 0; i < intervalCount; i++) {
            //创建一个存储点的数组
            ArrayList points = new ArrayList<>();
            for (int j = 0; j < data.size(); j++) {
                float r = R * ((float) (4 - i) / intervalCount);  //每一圈的半径都按比例减少
                //这里减去Math.PI / 2 是为了让多边形逆时针旋转90度,所以后面的所有用到cos,sin的都要减
                x = (float) (r * Math.cos(j * angle - Math.PI / 2));
                y = (float) (r * Math.sin(j * angle - Math.PI / 2));
                points.add(new PointF(x, y));
            }
            pointsArrayList.add(points);
        }
    }
}

怎么使用呢?使用如下:【这是我代码里面这样使用的】

 其中用到了一个Bean类:

/**
 * 今年居然不发年终奖,哎
 */
public class AbilityBean {

    public String name = "";//能力的名称
    public int num;//能力的值,范围0~100,单位%
    public int id;//能力的ID

    public AbilityBean(String name, int num, int id) {
        this.name = name;
        this.num = num;
        this.id = id;
    }

    public AbilityBean() {

    }
}

应该就可以直接使用了

你可能感兴趣的:(开发新技术,技术总结,自定义View,五星分析,仿联盟效果,五星图,5星战力)