仿探探的雷达探测View

作者: heyMan丶 | 来源:发表于2016-07-02 09:07 被阅读651次

    写点东西记录下,分享下,愿大家能一起成长。..
    打开"探探"的app,就在首页你可能会发现一个蛮有意思的View,看起来像雷达探测,个人感觉效果蛮好的。如果你也觉得有意思,喜欢的话那么就继续看看下面的内容吧。
    由于时间问题,只仿了8成左右,有一些地方还可以再改进改进的,因为体验还是比原版的要差些,如果项目要用的话可能也需要自己改动改动。
    下面就要开始了,如果发现有什么不对的或者可以有更好的实现的话,请告诉我吧,及时改正一同进步。~~
    首先先上张效果图看看:

    GIF.gif

    不点击中间图片的话,只有外圈在旋转,看起来就像雷达探测一样。点击中间图片中间图片会进行缩放,还会产生"波纹",效果看起蛮好玩吧。

    接下来先看定义的变量吧:

    /**中间的图片*/
    private Bitmap mBitmap;
    /**图片宽度*/
    private int mBitmapWidth;
    /**图片的高度*/
    private int mBitmapHeight;
    /** 图片是否被点击*/
    private boolean mIsTouchBitmap = false;
    /** 图片缩放的比值*/
    private float[] s = {1.05f, 1.1f, 1.15f, 1.2f, 1.25f, 1.2f, 1.1f, 1.0f, 0.9f, 0.8f, 0.75f, 0.8f, 0.9f, 1.0f};
    /**图片缩放的下标*/
    private int mScaleIndex = 0;
    /**波纹的画笔*/
    private Paint mCirclePaint;
    /** 点击生成的波纹  记录波纹的半径*/
    private List<Integer> mCircleRadiusArray = new ArrayList<>();
    /** 外部圆的半径*/
    private int mExternalCircleRadius;
    /** 初始圆的半径大小*/
    private int mInitCircleRadius;
    /** 外围旋转的雷达图片*/
    private Bitmap mRadarBitmap;
    /** 主要用于外围雷达的旋转*/
    private Matrix mRadarMatrix;
    /** 旋转的角度*/
    private int mRotateDegree;
    

    接下来我们初始化一些需要后面需要用到的东西,加载图片,波纹的画笔,设置初始波纹的半径,和外圈的Matrix(用于旋转)。
    <pre>
    private void init() {
    //加载图片
    mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.welcome_radar_image);
    mBitmapWidth = mBitmap.getWidth();
    mBitmapHeight = mBitmap.getHeight();
    //初始波纹的半径 设置 比图片的半径多20
    mInitCircleRadius = mBitmapWidth / 2 + 20;
    //波纹画笔的初始化
    mCirclePaint = new Paint();
    mCirclePaint.setColor(getResources().getColor(android.R.color.holo_red_light));
    mCirclePaint.setStrokeWidth(10.0f);
    mCirclePaint.setAntiAlias(true);
    mCirclePaint.setStyle(Paint.Style.STROKE);
    //主要用于外圈的旋转
    mRadarMatrix = new Matrix();
    }
    </pre>

    接下来设置计算View的宽度和高度,如果布局中layout_width是wrap_content的话,这里偷懒,View的宽度就为:图片的宽度+400,高度也是一样的。

    <pre>
    private int measureWidth(int measureSpec) {
    int result = mBitmapWidth + 400;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if (specMode == MeasureSpec.EXACTLY) {
    result = specSize;
    } else {
    result += getPaddingLeft()
    + getPaddingRight();
    if (specMode == MeasureSpec.AT_MOST) {
    // Respect AT_MOST value if that was what is called for by measureSpec
    result = Math.min(result, specSize);
    }
    }
    return result;
    }
    </pre>

    <pre>
    private int measureHeight(int measureSpec) {
    int result = mBitmapHeight + 400;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if (specMode == MeasureSpec.EXACTLY) {

            result = specSize;
        } else {
            result += getPaddingTop()
                    + getPaddingBottom();
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }
    

    </pre>

    初始下外圈雷达的图片,加载了图片后发现图片有点下,所以用matrix放大下图片
    <pre>
    //外圈的半径
    mExternalCircleRadius = getWidth() / 2 - 10;
    //外圈的图片
    mRadarBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.radar);
    //根据外圈的半径和图片的大小计算放大的比例,然后放大~~
    Matrix matrix = new Matrix();
    matrix.setScale(mExternalCircleRadius * 2.0f / mRadarBitmap.getWidth(), mExternalCircleRadius * 2.0f / mRadarBitmap.getHeight());
    //生成放大后的外圈图片
    mRadarBitmap = Bitmap.createBitmap(mRadarBitmap, 0, 0, mRadarBitmap.getWidth(), mRadarBitmap.getHeight(), matrix, true);
    </pre>

    接下来看下onDraw的方法:
    <pre>
    protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //外圈开始自动旋转
    startRotateRadar(canvas);
    //是否中间的图片是否被点击,如果被点击了就开始缩放图片,否则就画一个中间的图不动就好
    if (mIsTouchBitmap) {
    touchBitmapEvent(canvas);
    } else {
    canvas.drawBitmap(mBitmap, getWidth() / 2 - mBitmapWidth / 2, getHeight() / 2 - mBitmapHeight / 2, null);

        }
        //如果点击了就会生成波纹,就是这个方法开始画波纹的
        startWave(canvas);
    }
    

    </pre>

    按顺序我们先看外圈旋转的实现:
    <pre>
    /**
    * 开始雷达
    */
    private void startRotateRadar(Canvas canvas) {
    //旋转角度每次加2就好了
    mRotateDegree = mRotateDegree + 2;
    //开始旋转画图
    mRadarMatrix.setRotate(mRotateDegree, mRadarBitmap.getWidth() / 2, mRadarBitmap.getHeight() / 2);
    canvas.drawBitmap(mRadarBitmap, mRadarMatrix, null);
    //每次都是延迟35毫秒进行重绘
    postInvalidateDelayed(35);
    }
    </pre>

    接下来我们看点击事件和中间图片缩放的实现:
    1.实现onTouchEvent()
    <pre>
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

        //计算不在点击返回的空间
        int leftSpace = (getWidth() - mBitmapWidth) / 2;
        int rightSpce = leftSpace + mBitmapWidth;
        int topSpace = (getHeight() - mBitmapHeight) / 2;
        int bottomSpace = topSpace + mBitmapHeight;
    
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                //判断是否在点击图片
                if (x > leftSpace && x < rightSpce && y > topSpace && y < bottomSpace) {
                    //中间图片被点击
                    mIsTouchBitmap = true;
                    //缩放下标从0开始
                    mScaleIndex = 0;
                    //波纹出现的时间延长一点时间
                    postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mCircleRadiusArray.add(mInitCircleRadius);
                        }
                    }, 400);
                }
                break;
        }
        return true;
    }
    

    </pre>

    <pre>
    /**
    * 点击图片对图片进行放大缩小
    */
    private void touchBitmapEvent(Canvas canvas) {
    if (mIsTouchBitmap) {
    if (mScaleIndex < s.length) {
    //点击对图片进行缩放和移动处理
    Matrix matrix = new Matrix();
    matrix.setScale(s[mScaleIndex], s[mScaleIndex], mBitmap.getWidth() / 2, mBitmap.getHeight() / 2);
    matrix.postTranslate(getWidth() / 2 - mBitmap.getWidth() / 2, getHeight() / 2 - mBitmap.getHeight() / 2);
    canvas.drawBitmap(mBitmap, matrix, null);
    mScaleIndex++;
    } else {
    //缩放完成..这个可能要改下
    canvas.drawBitmap(mBitmap, getWidth() / 2 - mBitmapWidth / 2, getHeight() / 2 - mBitmapHeight / 2, null);
    mIsTouchBitmap = false;
    }
    }
    }
    </pre>

    如果点击了,也就是在onTouchEvent方法中mIsTouchBitmap赋值为true后波纹就开始了
    <pre>
    /** 开始画波纹*/
    private void startWave(Canvas canvas) {
    //每次点击都会添加波纹的半径到数组里面
    if (mCircleRadiusArray.size() > 0) {
    for (int i = 0; i < mCircleRadiusArray.size(); i++) {
    //如果超过外圆的半径就移除
    if (mCircleRadiusArray.get(i) > mExternalCircleRadius - 5) {
    mCircleRadiusArray.remove(i);
    } else {
    mCircleRadiusArray.set(i, mCircleRadiusArray.get(i) + 5);
    //越接近外圈颜色越来越浅
    float distance = mExternalCircleRadius - mCircleRadiusArray.get(i);
    int circleAlpha = (int) (255.0f * (distance / (mExternalCircleRadius - mInitCircleRadius)));

                    //越接近外圈波纹越细小
                    float circleWidth = 10.0f * (distance / (mExternalCircleRadius - mInitCircleRadius));
    

    //
    mCirclePaint.setAlpha(circleAlpha);
    mCirclePaint.setStrokeWidth(circleWidth);
    canvas.drawCircle(getWidth() / 2, getWidth() / 2, mCircleRadiusArray.get(i), mCirclePaint);
    }
    }
    }
    }
    </pre>

    好了..这就是这个View的实现
    Github地址:https://github.com/yuboxiaog/RadarDemo
    如果有什么错误的地方请见谅~~。

    相关文章

      网友评论

        本文标题:仿探探的雷达探测View

        本文链接:https://www.haomeiwen.com/subject/adofjttx.html