自定控件实现雷达监测功能

需求:雷达分为单点避障雷达和多点避障雷达,单点避障雷达又分为前后避障,多点避障雷达也分为前后避障,前避障和后避障都涉及到8个方向的避障,例如前避障的4个角度分别为-30~-15,-15~0,0~15,15~30。4个区间的雷达探测距离分别<10m(显示红红红),10-15m(显示黄黄红),>15m(显示绿绿绿)三个区间,等于25.5米则为无效点。效果如图所示,左图为单点避障雷达效果,右图为多点雷达效果。

                                             

1.设置自定义控件相关的属性,在attr文件中:

<declare-styleable name="RadarView">
    <attr name="firstColor" format="color" />//第一层的颜色
    <attr name="secondColor" format="color" />//第二层的颜色
    <attr name="thirdColor" format="color" />//第三层的颜色
    <attr name="stroke_width" format="dimension" />//圆弧的宽度
    <attr name="divider_width" format="dimension" />//圆弧之间的间隔
    <attr name="text_color_1" format="color" />//实时变化的距离的颜色
    <attr name="text_color_2" format="color" />//10M,15M的文字颜色
    <attr name="text_size_1" format="dimension" />//上面对应的文字的大小
    <attr name="text_size_2" format="dimension" />//上面对应的文字的大小
</declare-styleable>

2.开始自定义控件

package com.example.myapplication3;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.view.View;

import java.util.Locale;

/**
 * @author Kit Zuo
 * 2428382937@qq.com
 * @create 2019/12/05
 * @Desc 自定义控件实现避障雷达图
 */
public class RadarView extends View {
    private float text_size_1;
    private float text_size_2;
    private float stroke_width;
    private float divide_width;
    private int textColor_1;
    private int textColor_2;
    private int thirdColor;
    private int secondColor;
    private int firstColor;
    private Paint mFirstPaint;
    private Paint mSecondPaint;
    private Paint mThirdPaint;
    private Paint mTextPaint;
    private Paint mLinePaint;
    // 半径
    private float inner_radius = 100f;
    // 中心点
    private float centerX = 100f;
    private float centerY = 100f;
    // 开始角度
    private RectF rect_first;
    private RectF rect_second;
    private RectF rect_third;
    private float start_angle = 270;
    private static final float origin_angel = -60f;
    private static final float angel_divider = 30f;
    private float radius_third;
    private float radius_second;
    private Path path;//多点前避障的path
    private Path path_back;多点后避障的path
    private Path path_single;//单点前避障的path
    private Path path_single_back;//单点后避障的path
    private boolean isShowBac = true;//是否连接了后避障雷达
    private boolean isRadarType_multi = true;//是否是多点避障雷达
    private static final int multi_count = 4;//显示的角度区间个数
    private float angle;

    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);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RadarView);
        this.firstColor = typedArray.getColor(R.styleable.RadarView_firstColor, Color.parseColor("#ff0000"));
        this.secondColor = typedArray.getColor(R.styleable.RadarView_secondColor, Color.parseColor("#ffcc00"));
        this.thirdColor = typedArray.getColor(R.styleable.RadarView_thirdColor, Color.parseColor("#00ff00"));
        this.textColor_1 = typedArray.getColor(R.styleable.RadarView_text_color_1, Color.parseColor("#ff6600"));
        this.textColor_2 = typedArray.getColor(R.styleable.RadarView_text_color_2, Color.parseColor("#ffffff"));
        this.stroke_width = typedArray.getDimension(R.styleable.RadarView_stroke_width, 30);
        this.divide_width = typedArray.getDimension(R.styleable.RadarView_divider_width, 60);
        this.text_size_1 = typedArray.getDimension(R.styleable.RadarView_text_size_1, 20);
        this.text_size_2 = typedArray.getDimension(R.styleable.RadarView_text_size_2, 30);
        typedArray.recycle();
        init();
    }

    private void init() {

        mTextPaint = new Paint();
        mTextPaint.setStyle(Paint.Style.STROKE);
        mTextPaint.setStrokeWidth(2);
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(text_size_1);
        mTextPaint.setColor(Color.BLACK);
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        int windowHeight = DensityUtil.getWindowHeight(getContext());
        int windowWidth = DensityUtil.getWindowWidth(getContext());
        mThirdPaint = new Paint();
        mThirdPaint.setStyle(Paint.Style.STROKE);
        mThirdPaint.setStrokeWidth(stroke_width);
        mThirdPaint.setAntiAlias(true);

        mSecondPaint = new Paint();
        mSecondPaint.setStyle(Paint.Style.STROKE);
        mSecondPaint.setStrokeWidth(stroke_width);
        mSecondPaint.setAntiAlias(true);

        mFirstPaint = new Paint();
        mFirstPaint.setStyle(Paint.Style.STROKE);
        mFirstPaint.setAntiAlias(true);
        mFirstPaint.setStrokeWidth(stroke_width);

        mLinePaint = new Paint();
        mLinePaint.setStyle(Paint.Style.STROKE);
        mLinePaint.setStrokeWidth(2);
        mLinePaint.setAntiAlias(true);
        mLinePaint.setColor(ContextCompat.getColor(getContext(), R.color.white));

        centerX = windowWidth >> 1;
        centerY = windowHeight >> 1;
        radius_third = inner_radius + divide_width * 2;
        radius_second = inner_radius + divide_width;

        rect_third = new RectF(centerX - radius_third, centerY - radius_third, centerX + radius_third, centerY + radius_third);
        rect_second = new RectF(centerX - radius_second, centerY - radius_second, centerX + radius_second, centerY + radius_second);
        rect_first = new RectF(centerX - inner_radius, centerY - inner_radius, centerX + inner_radius, centerY + inner_radius);

        path = new Path();
        path_back = new Path();
        path_single = new Path();
        path_single_back = new Path();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //-30,-15,-15-0,0-15,15-30
        if (isRadarType_multi) {
//            canvas.save();
//            canvas.rotate(angle,centerX,centerY);
            int size = dataRadar.size();
            if (size >= 0) {
                canvas.save();
                for (int n = 0; n < multi_count; n++) {
                    doColor(n);
                    float start_angle = origin_angel + this.start_angle;
                    canvas.drawArc(rect_second, start_angle, angel_divider, false, mSecondPaint);
                    canvas.drawArc(rect_first, start_angle, angel_divider, false, mFirstPaint);
                    path.addArc(rect_third, start_angle, angel_divider);
                    canvas.drawPath(path, mThirdPaint);
                    double v = Math.PI * (90 - angel_divider) / 180;
                    if (n < 3) {
                        float x_1 = (float) (centerX - (radius_third + stroke_width / 2) * Math.cos(v));
                        float y_1 = (float) (centerY - (radius_third + stroke_width / 2) * Math.sin(v));
                        float x_2 = (float) (centerX - (inner_radius - stroke_width / 2) * Math.cos(v));
                        float y_2 = (float) (centerY - (inner_radius - stroke_width / 2) * Math.sin(v));
                        canvas.drawLine(x_1, y_1, x_2, y_2, mLinePaint);
                    }
                    mTextPaint.setTextSize(text_size_2);
                    mTextPaint.setColor(textColor_2);
                    canvas.drawTextOnPath(String.format(Locale.US, "%.1f", avoid_dis[n]), path, 0, 10, mTextPaint);
                    canvas.rotate(angel_divider, centerX, centerY);
                }
                canvas.restore();
                float y_4 = centerY - (inner_radius - stroke_width / 2);
                float y_7 = centerY - (radius_second - stroke_width / 2);
                mTextPaint.setTextSize(text_size_1);
                mTextPaint.setColor(textColor_1);
                canvas.drawText("15M", centerX, y_7 - divide_width / 2 - 10, mTextPaint);
                canvas.drawText("10M", centerX, y_4 - divide_width / 2 - 10, mTextPaint);
                if (isShowBac) {
                    canvas.save();
                    for (int m = 4; m < multi_count * 2; m++) {
                        doColor(m);
                        float start_angle = 90 - origin_angel;
                        canvas.drawArc(rect_second, start_angle, -angel_divider, false, mSecondPaint);
                        canvas.drawArc(rect_first, start_angle, -angel_divider, false, mFirstPaint);
                        path_back.addArc(rect_third, start_angle, -angel_divider);
                        canvas.drawPath(path_back, mThirdPaint);
                        double v = Math.PI * (90 - angel_divider) / 180;
                        if (m < 7) {
                            float x_1 = (float) (centerX - (radius_third + stroke_width / 2) * Math.cos(v));
                            float y_1 = (float) (centerY + (radius_third + stroke_width / 2) * Math.sin(v));
                            float x_2 = (float) (centerX - (inner_radius - stroke_width / 2) * Math.cos(v));
                            float y_2 = (float) (centerY + (inner_radius - stroke_width / 2) * Math.sin(v));
                            canvas.drawLine(x_1, y_1, x_2, y_2, mLinePaint);
                        }
                        mTextPaint.setTextSize(text_size_2);
                        mTextPaint.setColor(textColor_2);
                        canvas.drawTextOnPath(String.format(Locale.US, "%.1f", avoid_dis_back[m - 4]), path_back, 0, 10, mTextPaint);
                        canvas.rotate(-angel_divider, centerX, centerY);
                    }
                    canvas.restore();
                    float y_5 = centerY + (inner_radius + stroke_width / 2);
                    float y_8 = centerY + (radius_second + stroke_width / 2);
                    mTextPaint.setTextSize(text_size_1);
                    mTextPaint.setColor(textColor_1);
                    canvas.drawText("15M", centerX, y_8 + divide_width / 2 - 10, mTextPaint);
                    canvas.drawText("10M", centerX, y_5 + divide_width / 2 - 10, mTextPaint);
                }
            }
//            canvas.restore();
        } else {
            doColor(8);
            float start_angle = origin_angel + this.start_angle + angel_divider;
            canvas.drawArc(rect_second, start_angle, angel_divider * 2, false, mSecondPaint);
            canvas.drawArc(rect_first, start_angle, angel_divider * 2, false, mFirstPaint);
            path_single.addArc(rect_third, start_angle, angel_divider * 2);
            canvas.drawPath(path_single, mThirdPaint);
            mTextPaint.setTextSize(text_size_2);
            mTextPaint.setColor(textColor_2);
            canvas.drawTextOnPath(String.format(Locale.US, "%.1f", single_avoid), path_single, 0, 10, mTextPaint);
            float y_4 = centerY - (inner_radius - stroke_width / 2);
            float y_7 = centerY - (radius_second - stroke_width / 2);
            mTextPaint.setTextSize(text_size_1);
            mTextPaint.setColor(textColor_1);
            canvas.drawText("15M", centerX, y_7 - divide_width / 2 - 10, mTextPaint);
            canvas.drawText("10M", centerX, y_4 - divide_width / 2 - 10, mTextPaint);
            if (isShowBac) {
                doColor(9);
                float start_angle_single = 90 - origin_angel - angel_divider;
                canvas.drawArc(rect_second, start_angle_single, -angel_divider * 2, false, mSecondPaint);
                canvas.drawArc(rect_first, start_angle_single, -angel_divider * 2, false, mFirstPaint);
                path_single_back.addArc(rect_third, start_angle_single, -angel_divider * 2);
                canvas.drawPath(path_single_back, mThirdPaint);
                mTextPaint.setTextSize(text_size_2);
                mTextPaint.setColor(textColor_2);
                canvas.drawTextOnPath(String.format(Locale.US, "%.1f", single_avoid_back), path_single_back, 0, 10, mTextPaint);
                float y_5 = centerY + (inner_radius + stroke_width / 2);
                float y_8 = centerY + (radius_second + stroke_width / 2);
                mTextPaint.setTextSize(text_size_1);
                mTextPaint.setColor(textColor_1);
                canvas.drawText("15M", centerX, y_8 + divide_width / 2 - 10, mTextPaint);
                canvas.drawText("10M", centerX, y_5 + divide_width / 2 - 10, mTextPaint);
            }
        }
    }

    private void doColor(int n) {
        int warn_index = dataRadar.get(n + 1);
        if (warn_index >= 1) {
            if (warn_index == 1) {
                mThirdPaint.setColor(thirdColor);
                mSecondPaint.setColor(thirdColor);
                mFirstPaint.setColor(thirdColor);
            } else if (warn_index == 2) {
                mThirdPaint.setColor(secondColor);
                mSecondPaint.setColor(secondColor);
                mFirstPaint.setColor(thirdColor);
            } else if (warn_index == 3) {
                mThirdPaint.setColor(firstColor);
                mSecondPaint.setColor(firstColor);
                mFirstPaint.setColor(firstColor);
            }
        } else {
            mThirdPaint.setColor(thirdColor);
            mSecondPaint.setColor(thirdColor);
            mFirstPaint.setColor(thirdColor);
        }
    }

    public void setCenter(float centerX, float centerY, float inner_radius, float start_angle) {
        this.start_angle = start_angle + 270;
        this.inner_radius = inner_radius;
        this.centerX = centerX;
        this.centerY = centerY;
        rect_third.set(new RectF(centerX - (inner_radius + divide_width * 2), centerY - (inner_radius + divide_width * 2), centerX + (inner_radius + divide_width * 2), centerY + (inner_radius + divide_width * 2)));
        rect_second.set(new RectF(centerX - (inner_radius + divide_width), centerY - (inner_radius + divide_width), centerX + (inner_radius + divide_width), centerY + (inner_radius + divide_width)));
        rect_first.set(new RectF(centerX - inner_radius, centerY - inner_radius, centerX + inner_radius, centerY + inner_radius));
        invalidate();
    }

    private float[] avoid_dis = {25.5f, 25.5f, 25.5f, 25.5f};//多点前避障4个区间的距离
    private float[] avoid_dis_back = {25.5f, 25.5f, 25.5f, 25.5f};//多点后避障4个区间的距离
    private float single_avoid;//单点前避障的探测距离
    private float single_avoid_back;//单点后避障的探测距离

    public void setDir(float[] avoid_dis) {
        this.avoid_dis = avoid_dis;
    }

    public void setDirBack(float[] avoid_dis) {
        this.avoid_dis_back = avoid_dis;
    }

    private SparseIntArray dataRadar = new SparseIntArray();

    public void setDataRadar(SparseIntArray dataRadar) {
        this.dataRadar = dataRadar;
        invalidate();
    }

    public boolean isShowBac() {
        return isShowBac;
    }

    public void setShowBac(boolean showBac) {
        isShowBac = showBac;
    }

    public boolean isRadarType_multi() {
        return isRadarType_multi;
    }

    public void setRadarType_multi(boolean radarType_multi) {
        isRadarType_multi = radarType_multi;
    }

    public float getSingle_avoid() {
        return single_avoid;
    }

    public void setSingle_avoid(float single_avoid) {
        this.single_avoid = single_avoid;
    }

    public float getSingle_avoid_back() {
        return single_avoid_back;
    }

    public void setSingle_avoid_back(float single_avoid_back) {
        this.single_avoid_back = single_avoid_back;
    }

    public void setAngle(float angle) {
        this.angle = angle;
    }
}

3.总结

这个自定义控件虽然非常的简单,用到的都是比较简单的数学知识,但是实际应用比较广泛,也比较有趣,所以记录一下。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值