仿探探的雷达探测View

写点东西记录下,分享下,愿大家能一起成长。..
打开"探探"的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
如果有什么错误的地方请见谅~~。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,898评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,401评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,058评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,539评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,382评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,319评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,706评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,370评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,664评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,715评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,476评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,326评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,730评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,003评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,275评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,683评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,877评论 2 335

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,128评论 25 707
  • 老夫为了今天是煞费苦心啊,哈哈哈哈一直想模仿探探的一个雷达搜索效果(探探应该用过吧,就是和陌陌类似的不可描述app...
    hongjay阅读 2,405评论 1 28
  • 第一回 死於夜幕降臨後的吻 第兩回 到了時間便渺無音訊 第三回了 死於在大海中心呼喊 引來浪與鲨鱼 然後連死兩回 ...
    Alfli阅读 274评论 0 2
  • (二)声音方向定位线索 1声音方向定位线索 (1)双耳强度差 (2)双耳时间差 (3)双耳周相差 原因: 两耳的距...
    楷歌Kale阅读 1,383评论 0 0