最近在项目中有用到雷达扫描动画,这个效果也常被用于扫描或定位等事件,通过一个小Demo对此进行一下总结。

动画截图如下:

Android的动画分两类:一类是Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变)。另一类就是 Frame动画,即顺序的播放事先做好的图像,与gif图片原理类似。

此处的基本思想是通过自定义雷达View,不断刷新和绘制雷达View实现扫描Tween动画。

1. 首先自定义雷达View,RadarView.java代码如下:

package com.example.radar;import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;public class RadarView extends View{private Paint circlePaint;//圆形画笔private Paint linePaint;//线形画笔private Paint sweepPaint;//扫描画笔SweepGradient sweepGradient;//扇形渐变Shaderint 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);}@Overrideprotected 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); //重写测量方法,保证获得的画布是正方形}@Overrideprotected 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长轴刻度}}}}}

其中,需要用到Android渲染图像和图形的Shader类的渐变扫描子类SweepGradient,通过设置起始颜色color0和结束的color1,渲染出围绕中心点的闭合圆形渐变效果。

SweepGradient对象颜色定义如下:

<?xml version="1.0" encoding="utf-8"?>
<resources><color name="start_color">#696969</color><color name="end_color">#20ffffff</color>
</resources>

2. 实现RadarView的扫描动画

activity_main.xml简单布局文件,添加自定义RadarView和控制按钮,代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ADD8E6"><com.example.radar.RadarViewandroid:id="@+id/radar" android:layout_width="300dp"android:layout_height="300dp"android:layout_centerInParent="true"android:visibility="invisible"/><Buttonandroid:id="@+id/btn" android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:layout_alignParentBottom="true"android:layout_marginBottom="10dp"android:text="start"android:textSize="16sp"/></RelativeLayout>

创建RadarView的扫描刷新线程RadarSweep,当在线程radarView调用postInvalidate()方法时,会刷新RadarView的onDraw()方法,随之degree变量增加旋转角度,sweepGradient产生旋转效果。

MainActivity.java代码如下:

package com.example.radar;import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;public class MainActivity extends Activity {private RadarView radarView;private Button btn;private Thread radarSweepThread;private boolean startRadar = true;@Overrideprotected 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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (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;@Overridepublic void run() {// TODO Auto-generated method stubwhile (!Thread.currentThread().isInterrupted() && i == 1) {try {radarView.postInvalidate();// 刷新radarView, 执行onDraw();Thread.sleep(10);// 暂停当前线程,更新UI线程} catch (InterruptedException e) {i = 0;// 结束当前扫描线程标志符break;}}}}}

其中,RadarView载入和淡出的动画代码如下:

\Radar\res\anim\radar_anim_enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" ><!-- 雷达动画由大到正常 --><scaleandroid: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\res\anim\radar_anim_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" ><!-- 雷达动画由正常到缩小退出 --><scaleandroid: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>

简单的自定义雷达动画Demo介绍到此结束,如果想要更复杂和逼真的效果,还可以添加更多的效果和功能:如在雷达扫描的表盘上添加随机发光点,以及增加雷达刷新线程的控制参数,实现其他线程事件对雷达扫描的监听,如完成某个事件后自动退出雷达扫描动画等。时间有限,不在此一一赘述。

Android自定义View实现雷达扫描动画相关推荐

  1. android 自定义view之雷达扫描,基于Android自定义控件实现雷达效果

    如何制作出类似雷达扫描的效果,具体方法如下 一.效果图 二.实现思路 1.自定义控件RadarView用来画雷达的效果图,可以自定义属性包括 backgroundColor:背景颜色 circleNu ...

  2. android 自定义 对号,Android自定义View实现打钩动画功能

    先上效果图 动图 静态图 1. 回顾 [Android自定义View:一个精致的打钩小动画]上一篇文章,我们已经实现了基本上实现了控件的效果了,但是...但是...过了三四天后,仔细看回自己写的代码, ...

  3. android 自定义view: 蛛网/雷达图(三)

    本系列自定义View全部采用kt 系统mac android studio: 4.1.3 kotlin version1.5.0 gradle: gradle-6.5-bin.zip 本篇效果: 蛛网 ...

  4. android圆形波纹按钮,android自定义View——圆形波纹扫描效果

    蓝牙项目,考虑到后面可能会用到这个扫描的效果,所以参照大神写好的控件,增加了自己需要使用的接口.也顺便巩固一下自定义view中各种零碎的知识点. 需要的效果图 先放一个效果图,点击中心图片开始动画,再 ...

  5. android显示绘图动画,Android自定义View绘图实现渐隐动画

    实现了一个有趣的小东西:使用自定义view绘图,一边画线,画出的线条渐渐变淡,直到消失.效果如下图所示: 用属性动画或者渐变填充(shader)可以做到一笔一笔的变化,但要想一笔渐变(手指不抬起边画边 ...

  6. Android自定义View:雷达图/蜘蛛网图

    运行效果图 雷达图结构分析 对雷达图进行结构拆分,得到一个清晰的思路,这些结构也就是需要绘制的部分.为了能够有更好的扩展性,我将它们作为可定制的属性暴露出来,以下是结构属性表: 结构 相关属性 描述 ...

  7. android+清除循环动画,android自定义View之(4)-一键清除动画

    android自定义View之(四)------一键清除动画 1.前言: 自己也是参考别人的一些自定义view例子,学习了一些基本的自定义view的方法.今天,我参考了一些资料,再结合自已的一些理解, ...

  8. android自定义View之(四)------一键清除动画

    1.前言: 自己也是参考别人的一些自定义view例子,学习了一些基本的自定义view的方法.今天,我参考了一些资料,再结合自已的一些理解,做了一个一键清除的动画.当年,我实现这个是用了几张图片,采用F ...

  9. android自定义View: 饼状图绘制(四)

    本系列自定义View全部采用kt 系统mac android studio: 4.1.3 kotlin version1.5.0 gradle: gradle-6.5-bin.zip 本篇效果: 画矩 ...

最新文章

  1. 做项目遇到问题 2 AWS NLP 剽窃RuntimeError: size mismatch, m1: [10 x 3], m2: [2 x 10]检测部署报错
  2. python中一共有多少个关键字-Python之33个关键字是哪些
  3. linux下安装nginx详细步骤_mac下安装nginx
  4. .net core中使用缓存(cache)
  5. 使用 typescript ,提升 vue 项目的开发体验(1)
  6. html5 banner特效,HTML5特效库 CSS3遮罩banner动画特效源码
  7. Flowable 数据库表结构 ACT_RU_VARIABLE
  8. 找出数组中只出现一次的数
  9. 谈谈OAB离线地址簿无法更新问题?(服务器是Exchange 2007和Exchange 2010)
  10. 3.手动搭建Maven项目
  11. MySQL查询语句格式总结
  12. Structs2-Action
  13. 解决微信小程序图片过大上传失败问题
  14. python3自动化软件发布系统pdf_Python 3自动化软件发布系统 -Django 2实战
  15. 制作字幕.html教程,手机拍的视频如何加字幕 字幕制作软件使用教程
  16. Exchange 日常管理六之:创建邮箱数据库
  17. 驾驶证到期换新证流程
  18. 火影_青鸟_中日罗马音
  19. 乐高JAVA编程_用乐高认真玩进行Design Sprint
  20. 基于arduino的灯光控制(easy版)

热门文章

  1. asp sql查询过滤空格_【技术干货】30个最适合初学者的SQL查询
  2. h5 plus/h5+规范使用,模块索引,教你如何去看h5+的手册
  3. PSM 倾向性匹配(一)基础知识
  4. virt-manager安装xp.iso
  5. 使用python 将稀疏矩阵保存为mtx格式文件
  6. 分享一些压箱底的福利网站
  7. 热爆NFT“MetaBunny”公开发售后飙升近35倍 首轮公开发售达1,000枚后结束
  8. java web个人博客开发(二产品设计)
  9. Java题库后台管理系统
  10. Saiku + Kylin 多维分析平台探索