写点东西记录下,分享下,愿大家能一起成长。..
打开"探探"的app,就在首页你可能会发现一个蛮有意思的View,看起来像雷达探测,个人感觉效果蛮好的。如果你也觉得有意思,喜欢的话那么就继续看看下面的内容吧。
由于时间问题,只仿了8成左右,有一些地方还可以再改进改进的,因为体验还是比原版的要差些,如果项目要用的话可能也需要自己改动改动。
下面就要开始了,如果发现有什么不对的或者可以有更好的实现的话,请告诉我吧,及时改正一同进步。~~
首先先上张效果图看看:
不点击中间图片的话,只有外圈在旋转,看起来就像雷达探测一样。点击中间图片中间图片会进行缩放,还会产生"波纹",效果看起蛮好玩吧。
接下来先看定义的变量吧:
/**中间的图片*/
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
如果有什么错误的地方请见谅~~。
网友评论