寫(xiě)點(diǎn)東西記錄下矫夷,分享下存谎,愿大家能一起成長(zhǎng)瞻凤。..
打開(kāi)"探探"的app,就在首頁(yè)你可能會(huì)發(fā)現(xiàn)一個(gè)蠻有意思的View,看起來(lái)像雷達(dá)探測(cè)冈敛,個(gè)人感覺(jué)效果蠻好的。如果你也覺(jué)得有意思鸣皂,喜歡的話那么就繼續(xù)看看下面的內(nèi)容吧抓谴。
由于時(shí)間問(wèn)題,只仿了8成左右,有一些地方還可以再改進(jìn)改進(jìn)的,因?yàn)轶w驗(yàn)還是比原版的要差些,如果項(xiàng)目要用的話可能也需要自己改動(dòng)改動(dòng)寞缝。
下面就要開(kāi)始了癌压,如果發(fā)現(xiàn)有什么不對(duì)的或者可以有更好的實(shí)現(xiàn)的話,請(qǐng)告訴我吧,及時(shí)改正一同進(jìn)步荆陆。~~
首先先上張效果圖看看:
不點(diǎn)擊中間圖片的話滩届,只有外圈在旋轉(zhuǎn),看起來(lái)就像雷達(dá)探測(cè)一樣被啼。點(diǎn)擊中間圖片中間圖片會(huì)進(jìn)行縮放帜消,還會(huì)產(chǎn)生"波紋",效果看起蠻好玩吧。
接下來(lái)先看定義的變量吧:
/**中間的圖片*/
private Bitmap mBitmap;
/**圖片寬度*/
private int mBitmapWidth;
/**圖片的高度*/
private int mBitmapHeight;
/** 圖片是否被點(diǎn)擊*/
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};
/**圖片縮放的下標(biāo)*/
private int mScaleIndex = 0;
/**波紋的畫(huà)筆*/
private Paint mCirclePaint;
/** 點(diǎn)擊生成的波紋 記錄波紋的半徑*/
private List<Integer> mCircleRadiusArray = new ArrayList<>();
/** 外部圓的半徑*/
private int mExternalCircleRadius;
/** 初始圓的半徑大小*/
private int mInitCircleRadius;
/** 外圍旋轉(zhuǎn)的雷達(dá)圖片*/
private Bitmap mRadarBitmap;
/** 主要用于外圍雷達(dá)的旋轉(zhuǎn)*/
private Matrix mRadarMatrix;
/** 旋轉(zhuǎn)的角度*/
private int mRotateDegree;
接下來(lái)我們初始化一些需要后面需要用到的東西,加載圖片浓体,波紋的畫(huà)筆泡挺,設(shè)置初始波紋的半徑,和外圈的Matrix(用于旋轉(zhuǎn))命浴。
<pre>
private void init() {
//加載圖片
mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.welcome_radar_image);
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
//初始波紋的半徑 設(shè)置 比圖片的半徑多20
mInitCircleRadius = mBitmapWidth / 2 + 20;
//波紋畫(huà)筆的初始化
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);
//主要用于外圈的旋轉(zhuǎn)
mRadarMatrix = new Matrix();
}
</pre>
接下來(lái)設(shè)置計(jì)算View的寬度和高度,如果布局中l(wèi)ayout_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>
初始下外圈雷達(dá)的圖片,加載了圖片后發(fā)現(xiàn)圖片有點(diǎn)下生闲,所以用matrix放大下圖片
<pre>
//外圈的半徑
mExternalCircleRadius = getWidth() / 2 - 10;
//外圈的圖片
mRadarBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.radar);
//根據(jù)外圈的半徑和圖片的大小計(jì)算放大的比例媳溺,然后放大~~
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>
接下來(lái)看下onDraw的方法:
<pre>
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//外圈開(kāi)始自動(dòng)旋轉(zhuǎn)
startRotateRadar(canvas);
//是否中間的圖片是否被點(diǎn)擊,如果被點(diǎn)擊了就開(kāi)始縮放圖片,否則就畫(huà)一個(gè)中間的圖不動(dòng)就好
if (mIsTouchBitmap) {
touchBitmapEvent(canvas);
} else {
canvas.drawBitmap(mBitmap, getWidth() / 2 - mBitmapWidth / 2, getHeight() / 2 - mBitmapHeight / 2, null);
}
//如果點(diǎn)擊了就會(huì)生成波紋碍讯,就是這個(gè)方法開(kāi)始畫(huà)波紋的
startWave(canvas);
}
</pre>
按順序我們先看外圈旋轉(zhuǎn)的實(shí)現(xiàn):
<pre>
/**
* 開(kāi)始雷達(dá)
*/
private void startRotateRadar(Canvas canvas) {
//旋轉(zhuǎn)角度每次加2就好了
mRotateDegree = mRotateDegree + 2;
//開(kāi)始旋轉(zhuǎn)畫(huà)圖
mRadarMatrix.setRotate(mRotateDegree, mRadarBitmap.getWidth() / 2, mRadarBitmap.getHeight() / 2);
canvas.drawBitmap(mRadarBitmap, mRadarMatrix, null);
//每次都是延遲35毫秒進(jìn)行重繪
postInvalidateDelayed(35);
}
</pre>
接下來(lái)我們看點(diǎn)擊事件和中間圖片縮放的實(shí)現(xiàn):
1.實(shí)現(xiàn)onTouchEvent()
<pre>
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
//計(jì)算不在點(diǎn)擊返回的空間
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:
//判斷是否在點(diǎn)擊圖片
if (x > leftSpace && x < rightSpce && y > topSpace && y < bottomSpace) {
//中間圖片被點(diǎn)擊
mIsTouchBitmap = true;
//縮放下標(biāo)從0開(kāi)始
mScaleIndex = 0;
//波紋出現(xiàn)的時(shí)間延長(zhǎng)一點(diǎn)時(shí)間
postDelayed(new Runnable() {
@Override
public void run() {
mCircleRadiusArray.add(mInitCircleRadius);
}
}, 400);
}
break;
}
return true;
}
</pre>
<pre>
/**
* 點(diǎn)擊圖片對(duì)圖片進(jìn)行放大縮小
*/
private void touchBitmapEvent(Canvas canvas) {
if (mIsTouchBitmap) {
if (mScaleIndex < s.length) {
//點(diǎn)擊對(duì)圖片進(jìn)行縮放和移動(dòng)處理
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 {
//縮放完成..這個(gè)可能要改下
canvas.drawBitmap(mBitmap, getWidth() / 2 - mBitmapWidth / 2, getHeight() / 2 - mBitmapHeight / 2, null);
mIsTouchBitmap = false;
}
}
}
</pre>
如果點(diǎn)擊了,也就是在onTouchEvent方法中mIsTouchBitmap賦值為true后波紋就開(kāi)始了
<pre>
/** 開(kāi)始畫(huà)波紋*/
private void startWave(Canvas canvas) {
//每次點(diǎn)擊都會(huì)添加波紋的半徑到數(shù)組里面
if (mCircleRadiusArray.size() > 0) {
for (int i = 0; i < mCircleRadiusArray.size(); i++) {
//如果超過(guò)外圓的半徑就移除
if (mCircleRadiusArray.get(i) > mExternalCircleRadius - 5) {
mCircleRadiusArray.remove(i);
} else {
mCircleRadiusArray.set(i, mCircleRadiusArray.get(i) + 5);
//越接近外圈顏色越來(lái)越淺
float distance = mExternalCircleRadius - mCircleRadiusArray.get(i);
int circleAlpha = (int) (255.0f * (distance / (mExternalCircleRadius - mInitCircleRadius)));
//越接近外圈波紋越細(xì)小
float circleWidth = 10.0f * (distance / (mExternalCircleRadius - mInitCircleRadius));
//
mCirclePaint.setAlpha(circleAlpha);
mCirclePaint.setStrokeWidth(circleWidth);
canvas.drawCircle(getWidth() / 2, getWidth() / 2, mCircleRadiusArray.get(i), mCirclePaint);
}
}
}
}
</pre>
好了..這就是這個(gè)View的實(shí)現(xiàn)
Github地址:https://github.com/yuboxiaog/RadarDemo
如果有什么錯(cuò)誤的地方請(qǐng)見(jiàn)諒~~悬蔽。