Android:自定义view 实现雷达扫描效果

时间:2023-02-09 09:11:56

前几天我的app上加了一个雷达扫描来查询附件商家的效果。看起来还是挺不错的,现在把雷达扫描的效果分享给大家。

最近项目新版刚上线,不是很忙,所以多抽出了一些时间来整理一下博客。

那书归正传:

先上效果图
Android:自定义view 实现雷达扫描效果

图片有点失真,不要介意,先介绍下,主要用了Paint(画笔)+ canvas(画布) (以后我会专门写一篇文章来介绍paint和canvas,这里先认为大家都懂得paint和canvas的相关知识)

先看图,主要有几个点需要完成:

1.背景有五个半径不同的园。
2.类似于扫描的渲染效果。
3.让整个布局转起来。

好,咱们一个一个来。
第一个比较简单,用paint在canvas画五个大小不一的圆。
第二个用SweepGradient 增加渲染效果。
第三个让canvas的矩阵旋转变换。

下面直接上代码,注释比较全就不在多加修饰了。

/**
* 雷达扫描 自定义view
*
* @author Bihaidong
* @date 2016-9-18 9:46:09
*/

public class CustomView extends View {

private int mWidth, mHeight;

private float[] pots = {0.05f, 0.1f, 0.15f, 0.2f, 0.25f};

private Shader scanShader; // 扫描渲染shader
private Matrix matrix = new Matrix(); // 旋转需要的矩阵
private int scanSpeed = 5; // 扫描速度
private int scanAngle; // 扫描旋转的角度

private Paint mPaintCircle; // 画圆用到的paint
private Paint mPaintRadar; // 扫描用到的paint


public CustomView(Context context) {
super(context);

// 画圆用到的paint
mPaintCircle = new Paint();
mPaintCircle.setStyle(Paint.Style.STROKE); // 描边
mPaintCircle.setStrokeWidth(1); // 宽度
mPaintCircle.setAlpha(100); // 透明度
mPaintCircle.setAntiAlias(true); // 抗锯齿
mPaintCircle.setColor(Color.parseColor("#B0C4DE")); // 设置颜色 亮钢兰色

// 扫描用到的paint
mPaintRadar = new Paint();
mPaintRadar.setStyle(Paint.Style.FILL_AND_STROKE); // 填充
mPaintRadar.setAntiAlias(true); // 抗锯齿

post(run);
}

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

for (int i = 0; i < pots.length; i++) {
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[i], mPaintCircle);
}

// 画布的旋转变换 需要调用save() 和 restore()
canvas.save();

scanShader = new SweepGradient(mWidth / 2, mHeight / 2,
new int[]{Color.TRANSPARENT, Color.parseColor("#84B5CA")}, null);
mPaintRadar.setShader(scanShader); // 设置着色器
canvas.concat(matrix);
canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[4], mPaintRadar);

canvas.restore();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

// 取屏幕的宽高是为了把雷达放在屏幕的中间
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
mWidth = mHeight = Math.min(mWidth, mHeight);
}

private Runnable run = new Runnable() {
@Override
public void run() {
scanAngle = (scanAngle + scanSpeed) % 360; // 旋转角度 对360取余
matrix.postRotate(scanSpeed, mWidth / 2, mHeight / 2); // 旋转矩阵
invalidate(); // 通知view重绘
postDelayed(run, 130); // 调用自身 重复绘制
}
};
}