Android自定义View实现雷达扫描动画

前言:类似社交软件的雷达搜索:

MainActivity:

public class MainActivity extends Activity {
	private RadarView radarView;
	private Button btn;
	private Thread radarSweepThread;
	private boolean startRadar = true;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		radarView = (RadarView) findViewById(R.id.radar);
		btn = (Button) findViewById(R.id.btn);
		btn.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				if (startRadar) {
					btn.setText("end");
					radarView.setVisibility(View.VISIBLE);// 设置可见
					Animation radarAnimEnter = AnimationUtils.loadAnimation(
							MainActivity.this, R.anim.radar_anim_enter);// 初始化radarView进入动画
					radarView.startAnimation(radarAnimEnter);// 开始进入动画
					radarSweepThread = new Thread(new RadarSweep());// 雷达扫描线程
					radarSweepThread.start();
					startRadar = false;
				} else {
					btn.setText("start");
					Animation radarAnimEnter = AnimationUtils.loadAnimation(
							MainActivity.this, R.anim.radar_anim_exit);// 初始化radarView退出动画
					radarView.startAnimation(radarAnimEnter);// 开始进入动画
					radarView.setVisibility(View.INVISIBLE);// 设置不可见
					radarSweepThread.interrupt();// 停止扫描更新
					startRadar = true;
				}
			}
		});
	}
	/**
	 * @ClassName RadarSweep
	 * @Description 雷达扫描动画刷新线程类
	 */
	private class RadarSweep implements Runnable {
		int i = 1;
		@Override
		public void run() {
			// TODO Auto-generated method stub
			//无限判断当前线程状态,如果没有中断,就一直执行while内容
			//如果中断返回true,否则返回false
			while (!Thread.currentThread().isInterrupted() && i == 1) {
				try {
					radarView.postInvalidate();// 刷新radarView, 执行onDraw();
					Thread.sleep(10);// 暂停当前线程,更新UI线程(注释掉貌似没影响)
				} catch (InterruptedException e) {
					i = 0;// 结束当前扫描线程标志符
					break;
				}
			}
		}
	}
}

自定义View:

public class RadarView extends View {
	private Paint circlePaint;// 圆形画笔
	private Paint linePaint;// 线形画笔
	private Paint sweepPaint;// 扫描画笔
	SweepGradient sweepGradient;// 扇形渐变Shader
	int degree = 0;
	public RadarView(Context context) {
		super(context);
	}
	public RadarView(Context context, AttributeSet att) {
		super(context, att);
		initPaint();
	}
	/**
	 * @param
	 * @return void
	 * @Description //初始化定义的画笔
	 */
	private void initPaint() {
		Resources r = this.getResources();
		circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);// 圆形画笔,设置Paint为抗锯齿
		circlePaint.setARGB(255, 50, 57, 74);// 设置透明度和RGB颜色
		circlePaint.setStrokeWidth(3);// 轮廓宽度
		circlePaint.setStyle(Paint.Style.STROKE);
		linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);// 线性画笔
		linePaint.setStrokeCap(Paint.Cap.ROUND);
		linePaint.setARGB(150, 50, 57, 74);
		linePaint.setStrokeWidth(2);
		sweepPaint = new Paint(Paint.ANTI_ALIAS_FLAG);// 雷达Shader画笔
		sweepPaint.setStrokeCap(Paint.Cap.ROUND);
		sweepPaint.setStrokeWidth(4);
		sweepGradient = new SweepGradient(0, 0,
				r.getColor(R.color.start_color), r.getColor(R.color.end_color));
		sweepPaint.setShader(sweepGradient);//绘制梯度渐变,这里是渐变设置的方法
	}
	@Override
	protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
		int width = MeasureSpec.getSize(wMeasureSpec);
		int height = MeasureSpec.getSize(hMeasureSpec);
		int d = (width >= height) ? height : width; // 获取最短的边作为直径
		setMeasuredDimension(d, d); // 重写测量方法,保证获得的画布是正方形
	}
	@Override
	protected void onDraw(Canvas canvas) {
		int Width = getMeasuredWidth();// //计算控件的中心位置
		int Height = getMeasuredHeight();
		int pointX = Width / 2;// 获得圆心坐标
		int pointY = Height / 2;
		int radius = (pointX >= pointY) ? pointY : pointX;// 设置半径
		radius -= 10;// 设置半径
		canvas.save();// 保存Canvas坐标原点
		degree += 5;// 扫描旋转增量度数
		canvas.translate(pointX, pointY);// 设置旋转的原点
		canvas.rotate(270 + degree);
		canvas.drawCircle(0, 0, radius, sweepPaint);// 绘制扫描区域
		canvas.restore();// 恢复原Canvas坐标(0,0)
		canvas.drawCircle(pointX, pointY, radius, circlePaint);// 绘制3个嵌套同心圆形,使用circlePaint画笔
		circlePaint.setAlpha(100);// 降低内部圆形的透明度
		circlePaint.setStrokeWidth(2);// 轮廓宽度
		canvas.drawCircle(pointX, pointY, radius * 2 / 3, circlePaint);
		canvas.drawCircle(pointX, pointY, radius / 3, circlePaint);
		canvas.drawLine(pointX, 10, pointX, 2 * radius + 10, linePaint);// 绘制十字分割线
																		// , 竖线
		canvas.drawLine(10, pointY, 2 * radius + 10, pointY, linePaint);
		canvas.save();// 保存Canvas坐标原点
		canvas.translate(10, radius + 10);// 设置相对横线起始坐标
		float s = radius / 12f;// 刻度间距
		float minlength = s / 2;// 短刻度线长度
		float maxlength = s;// 长刻度线长度
		for (int i = 0; i < 24; i++) {
			float fromX, toX;
			fromX = toX = s * i;
			if (i % 4 != 0) {// 与圆形重叠处不画刻度
				if (i % 2 != 0) {
					canvas.drawLine(fromX, -minlength, toX, minlength,
							linePaint);// 绘制X轴短刻度
				} else {
					canvas.drawLine(fromX, -maxlength, toX, maxlength,
							linePaint);// 绘制X轴长刻度
				}
			}
		}
		canvas.restore();
		canvas.translate(pointX, 10);// 设置相对竖线起始坐标
		for (int i = 0; i < 24; i++) {
			float fromY, toY;
			fromY = toY = s * i;
			if (i % 4 != 0) {
				if (i % 2 != 0) {
					canvas.drawLine(-minlength, fromY, minlength, toY,
							linePaint);// 绘制Y短轴刻度
				} else {
					canvas.drawLine(-maxlength, fromY, maxlength, toY,
							linePaint);// 绘制Y长轴刻度
				}
			}
		}
	}
}

进入动画:radar_anim_enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 雷达动画由大到正常 -->  
    <scale  
        android:duration="2000"  
        android:fromXScale="1.5"  
        android:fromYScale="1.5"  
        android:interpolator="@android:anim/decelerate_interpolator"  
        android:pivotX="50%"  
        android:pivotY="50%"  
        android:toXScale="1.0"  
        android:toYScale="1.0" />
</set>

退出动画:radar_anim_exit.xml

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android" >  
    <!-- 雷达动画由正常到缩小退出 -->  
    <scale  
        android:duration="1000"  
        android:fromXScale="1.0"  
        android:fromYScale="1.0"  
        android:interpolator="@android:anim/accelerate_interpolator"  
        android:pivotX="50%"  
        android:pivotY="50%"  
        android:toXScale="0.0"  
        android:toYScale="0.0" />  
</set>  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值