Android自定义控件实现雷达效果

一、效果图
这里写图片描述
二、实现思路
1、自定义控件RadarView用来画雷达的效果图,可以自定义属性包括
backgroundColor:背景颜色
circleNum:圆的数量
startColor:开始颜色
endColor:结束颜色
lineColor:线的颜色
2、通过Handler循环发送消息到MessageQueue中,将mRotate加3,使Matrix旋转mRotate,重绘雷达扫描的圆。
3、通过梯度渐变扫描渲染器SweepGradient,在绘制圆的过程中,将颜色从startColor变为endColor。
三、实例代码

public class RadarView extends View {
    private final String TAG = "RadarView";

    private static final int MSG_WHAT = 1;

    private static final int DELAY_TIME = 20;

    //设置默认宽高,雷达一般都是圆形,所以我们下面取宽高会取Math.min(宽,高)
    private final int DEFAULT_WIDTH = 200;

    private final int DEFAULT_HEIGHT = 200;
    //雷达的半径
    private int mRadarRadius;
    //雷达画笔
    private Paint mRadarPaint;
    //雷达底色画笔
    private Paint mRadarBg;
    //雷达圆圈的个数,默认4个
    private int mCircleNum = 4;
    //雷达线条的颜色,默认为白色
    private int mCircleColor = Color.WHITE;
    //雷达圆圈背景色
    private int mRadarBgColor = Color.BLACK;
    //paintShader
    private Shader mRadarShader;

    //雷达扫描时候的起始和终止颜色
    private int mStartColor = 0x0000ff00;

    private int mEndColor = 0xaa00ff00;


    private Matrix mMatrix;

    //旋转的角度
    private int mRotate = 0;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            mRotate += 3;
            postInvalidate();

            mMatrix.reset();
            mMatrix.preRotate(mRotate, 0, 0);
            //延时DELAY_TIME后再发送消息
            mHandler.sendEmptyMessageDelayed(MSG_WHAT, DELAY_TIME);
        }
    };

    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);
        init(context, attrs);

        //设置抗锯齿
        mRadarBg = new Paint(Paint.ANTI_ALIAS_FLAG);
        //画笔颜色
        mRadarBg.setColor(mRadarBgColor);
        //画实心圆
        mRadarBg.setStyle(Paint.Style.FILL);

        //设置抗锯齿
        mRadarPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //画笔颜色
        mRadarPaint.setColor(mCircleColor);
        //设置空心的画笔,只画圆边
        mRadarPaint.setStyle(Paint.Style.STROKE);
        //画笔宽度
        mRadarPaint.setStrokeWidth(2);
        //使用梯度渐变渲染器,
        mRadarShader = new SweepGradient(0, 0, mStartColor, mEndColor);

        mMatrix = new Matrix();
    }


    //初始化,拓展可设置参数供布局使用
    private void init(Context context, AttributeSet attrs) {
        if (attrs != null) {
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RadarView);
            mStartColor = ta.getColor(R.styleable.RadarView_startColor, mStartColor);
            mEndColor = ta.getColor(R.styleable.RadarView_endColor, mEndColor);
            mRadarBgColor = ta.getColor(R.styleable.RadarView_backgroundColor, mRadarBgColor);
            mCircleColor = ta.getColor(R.styleable.RadarView_lineColor, mCircleColor);
            mCircleNum = ta.getInteger(R.styleable.RadarView_circleNum, mCircleNum);
            ta.recycle();
        }
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //雷达的半径为宽的一半或高的一半的最小值
        mRadarRadius = Math.min(w / 2, h / 2);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取宽度
        int width = measureSize(1, DEFAULT_WIDTH, widthMeasureSpec);
        //获取高度
        int height = measureSize(0, DEFAULT_HEIGHT, heightMeasureSpec);

        //取最大的 宽|高
        int measureSize = Math.max(width, height);
        setMeasuredDimension(measureSize, measureSize);
    }


    /**
     * 测绘measure
     *
     * @param specType    1为宽, 其他为高
     * @param contentSize 默认值
     */
    private int measureSize(int specType, int contentSize, int measureSpec) {
        int result;
        //获取测量的模式和Size
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = Math.max(contentSize, specSize);
        } else {
            result = contentSize;

            if (specType == 1) {
                // 根据传入方式计算宽
                result += (getPaddingLeft() + getPaddingRight());
            } else {
                // 根据传入方式计算高
                result += (getPaddingTop() + getPaddingBottom());
            }
        }

        return result;

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Log.d(TAG, "onDraw   " + mRotate);

        mRadarBg.setShader(null);

        //将画布移动到屏幕的中心点
        canvas.translate(mRadarRadius, mRadarRadius);
        //绘制底色,让雷达的线看起来更清晰
        canvas.drawCircle(0, 0, mRadarRadius, mRadarBg);
        //画圆圈
        for (int i = 1; i <= mCircleNum; i++) {
            canvas.drawCircle(0, 0, (float) (i * 1.0 / mCircleNum * mRadarRadius), mRadarPaint);
        }
        //绘制雷达基线 x轴
        canvas.drawLine(-mRadarRadius, 0, mRadarRadius, 0, mRadarPaint);
        //绘制雷达基线 y轴
        canvas.drawLine(0, mRadarRadius, 0, -mRadarRadius, mRadarPaint);
        //设置颜色渐变从透明到不透明
        mRadarBg.setShader(mRadarShader);
        //设置矩阵
        canvas.concat(mMatrix);
        canvas.drawCircle(0, 0, mRadarRadius, mRadarBg);
    }


    public void startScan() {
        mHandler.removeMessages(MSG_WHAT);
        mHandler.sendEmptyMessage(MSG_WHAT);
    }

    public void stopScan() {
        mHandler.removeMessages(MSG_WHAT);
    }
}

布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <com.android.demo.ui.shader.RadarView
        android:id="@+id/radarview"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        app:backgroundColor="#000000"
        app:circleNum="4"
        app:endColor="#aaff0000"
        app:lineColor="#00ff00"
        app:startColor="#aa0000ff"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:onClick="start"
        android:text="开始" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:onClick="stop"
        android:text="停止" />
</RelativeLayout>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值