Android动画之雷达扫描效果
我们首先看一下效果图,有个整体的印象
好了,为了便于理解,这里就按照动画所见内容依次展开来说
准备
这里决定采用canvas(画布)和paint(画笔)实现了这个简单动画控件。
由图片可以看到有两条交叉的十字线、几个圆圈和一些白点,那么首先定义一下所需的画笔,画布及一些数据
setBackgroundColor(Color.TRANSPARENT); //宽度=5,抗锯齿,描边效果的白色画笔 mPaintLine = new Paint(); mPaintLine.setStrokeWidth(5); mPaintLine.setAntiAlias(true); mPaintLine.setStyle(Style.STROKE); mPaintLine.setColor(Color.WHITE); //宽度=5,抗锯齿,描边效果的浅绿色画笔 mPaintCircle = new Paint(); mPaintCircle.setStrokeWidth(5); mPaintCircle.setAntiAlias(true); mPaintCircle.setStyle(Style.FILL); mPaintCircle.setColor(0x99000000); //暗绿色的画笔 mPaintSector = new Paint(); mPaintSector.setColor(0x9D00ff00); mPaintSector.setAntiAlias(true); //定义一个暗绿色的梯度渲染 mShader = new SweepGradient(viewSize / 2, viewSize / 2, Color.TRANSPARENT, Color.GREEN); mPaintSector.setShader(mShader); //白色实心画笔 mPaintPoint=new Paint(); mPaintPoint.setColor(Color.WHITE); mPaintPoint.setStyle(Style.FILL); //随机生成一些数组点,模拟雷达扫描结果 point_x = UtilTools.Getrandomarray(15, 300); point_y = UtilTools.Getrandomarray(15, 300);
这里说一下这个SweepGradient
SweepGradient的构造函数:
public SweepGradient(float cx, float cy, int[] colors, float[] positions)
public SweepGradient(float cx, float cy, int color0, int color1)
其中cx,cy 指定圆心, color1,color0 或 colors 指定渐变的颜色 ,对于使用多于两种颜色时,还可以通过positions 指定每种颜色的相对位置,positions 设为NULL时表示颜色均匀分布。
绘制基本图形
canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintCircle); canvas.drawCircle(viewSize / 2, viewSize / 2, 255, mPaintLine); canvas.drawCircle(viewSize / 2, viewSize / 2, 125, mPaintLine); canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintLine); //绘制两条十字线 canvas.drawLine(viewSize / 2, 0, viewSize / 2, viewSize, mPaintLine); canvas.drawLine(0, viewSize / 2, viewSize, viewSize / 2, mPaintLine);
这样就绘制除了整个UI,接下来加上动画,就可以实现整体的效果。
动画实现
这里实现动画的时候,用到了Matrix这个东西,也就是矩阵。上学的时候,线性代数老师讲各种线性变换时,脑子里在想,这玩意是干嘛使得,现在总算是遇上了,现在看起来也是云里雾里。总的来说就是可以使用Matrix实现强大的图形动画,包括位移、旋转、缩放及透明变化等效果,matrix有着一系列的setTranslate,setRotate,setScale等方法。很方便的实现图形各种变换,主要还是需要理解各种变换。
动画实现线程
protected class ScanThread extends Thread { private RadarView view; public ScanThread(RadarView view) { // TODO Auto-generated constructor stub this.view = view; } @Override public void run() { // TODO Auto-generated method stub while (threadRunning) { if (isstart) { view.post(new Runnable() { public void run() { start = start + 1; matrix = new Matrix(); //设定旋转角度,制定进行转转操作的圆心 // matrix.postRotate(start, viewSize / 2, viewSize / 2); // matrix.setRotate(start,viewSize/2,viewSize/2); matrix.preRotate(direction*start,viewSize/2,viewSize/2); view.invalidate(); } }); try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
首先,这里在一个独立线程中不断的对start做累加,作为旋转角度。然后将其和matrix关联。这里尝试使用了matrix的三个方法,暂时没有发现区别。
动画绘制
接下来在onDraw方法中不断绘制图形即可
//根据matrix中设定角度,不断绘制shader,呈现出一种扇形扫描效果 canvas.concat(matrix); canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintSector);
最终实现
好了,最终整体的代码如下:
public class RadarView extends FrameLayout { private Context mContext; private int viewSize = 800; private Paint mPaintLine; private Paint mPaintCircle; private Paint mPaintSector; public boolean isstart = false; private ScanThread mThread; private Paint mPaintPoint; //旋转效果起始角度 private int start = 0; private int[] point_x; private int[] point_y; private Shader mShader; private Matrix matrix; public final static int CLOCK_WISE=1; public final static int ANTI_CLOCK_WISE=-1; @IntDef({ CLOCK_WISE, ANTI_CLOCK_WISE }) public @interface RADAR_DIRECTION { } //默认为顺时针呢 private final static int DEFAULT_DIERCTION=CLOCK_WISE; //设定雷达扫描方向 private int direction=DEFAULT_DIERCTION; private boolean threadRunning = true; public RadarView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub mContext = context; initPaint(); } public RadarView(Context context) { super(context); // TODO Auto-generated constructor stub mContext = context; initPaint(); } private void initPaint() { // TODO Auto-generated method stub setBackgroundColor(Color.TRANSPARENT); //宽度=5,抗锯齿,描边效果的白色画笔 mPaintLine = new Paint(); mPaintLine.setStrokeWidth(5); mPaintLine.setAntiAlias(true); mPaintLine.setStyle(Style.STROKE); mPaintLine.setColor(Color.WHITE); //宽度=5,抗锯齿,描边效果的浅绿色画笔 mPaintCircle = new Paint(); mPaintCircle.setStrokeWidth(5); mPaintCircle.setAntiAlias(true); mPaintCircle.setStyle(Style.FILL); mPaintCircle.setColor(0x99000000); //暗绿色的画笔 mPaintSector = new Paint(); mPaintSector.setColor(0x9D00ff00); mPaintSector.setAntiAlias(true); mShader = new SweepGradient(viewSize / 2, viewSize / 2, Color.TRANSPARENT, Color.GREEN); mPaintSector.setShader(mShader); //白色实心画笔 mPaintPoint=new Paint(); mPaintPoint.setColor(Color.WHITE); mPaintPoint.setStyle(Style.FILL); //随机生成的点,模拟雷达扫描结果 point_x = UtilTools.Getrandomarray(15, 300); point_y = UtilTools.Getrandomarray(15, 300); } public void setViewSize(int size) { this.viewSize = size; setMeasuredDimension(viewSize, viewSize); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub setMeasuredDimension(viewSize, viewSize); } public void start() { mThread = new ScanThread(this); mThread.setName("radar"); mThread.start(); threadRunning = true; isstart = true; } public void stop() { if (isstart) { threadRunning = false; isstart = false; } } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintCircle); canvas.drawCircle(viewSize / 2, viewSize / 2, 255, mPaintLine); canvas.drawCircle(viewSize / 2, viewSize / 2, 125, mPaintLine); canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintLine); //绘制两条十字线 canvas.drawLine(viewSize / 2, 0, viewSize / 2, viewSize, mPaintLine); canvas.drawLine(0, viewSize / 2, viewSize, viewSize / 2, mPaintLine); //这里在雷达扫描过制定圆周度数后,将随机绘制一些白点,模拟搜索结果 if (start > 100) { for (int i = 0; i < 2; i++) { canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint); } } if (start > 200) { for (int i = 2; i < 5; i++) { canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint); } } if (start > 300) { for (int i = 5; i < 9; i++) { canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint); } } if (start > 500) { for (int i = 9; i < 11; i++) { canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint); } } if (start > 800) { for (int i = 11; i < point_x.length; i++) { canvas.drawCircle(viewSize / 2 + point_x[i], viewSize / 2 + point_y[i], 10, mPaintPoint); } } //根据matrix中设定角度,不断绘制shader,呈现出一种扇形扫描效果 canvas.concat(matrix); canvas.drawCircle(viewSize / 2, viewSize / 2, 350, mPaintSector); super.onDraw(canvas); } public void setDirection(@RADAR_DIRECTION int direction) { if (direction != CLOCK_WISE && direction != ANTI_CLOCK_WISE) { throw new IllegalArgumentException("Use @RADAR_DIRECTION constants only!"); } this.direction = direction; } protected class ScanThread extends Thread { private RadarView view; public ScanThread(RadarView view) { // TODO Auto-generated constructor stub this.view = view; } @Override public void run() { // TODO Auto-generated method stub while (threadRunning) { if (isstart) { view.post(new Runnable() { public void run() { start = start + 1; matrix = new Matrix(); //设定旋转角度,制定进行转转操作的圆心 // matrix.postRotate(start, viewSize / 2, viewSize / 2); // matrix.setRotate(start,viewSize/2,viewSize/2); matrix.preRotate(direction*start,viewSize/2,viewSize/2); view.invalidate(); } }); try { Thread.sleep(5); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }
说明
多余的部分就不再解释,代码里已经注释的很清楚。这个RadarView的使用也是很简单,需要停止时,调用其stop方法即可。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RadarView radarView = (RadarView) findViewById(R.id.radar); //设置雷达扫描方向 radarView.setDirection(RadarView.ANTI_CLOCK_WISE); radarView.start(); }
这里雷达ViewSize设置为800,所以在布局文件中设定大小时将不起作用,正常使用时,需根据实际需求调整viewsize大小和几个Circle的半径,从而达到更有好的UI展示效果。
总结
以上就是Android中雷达扫描效果实现的全部内容,希望本文对大家Android开发有所帮助。
更多Android动画之雷达扫描效果相关文章请关注PHP中文网!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas





Penyelesaian masalah dan penyelesaian kepada perisian keselamatan syarikat yang menyebabkan beberapa aplikasi tidak berfungsi dengan baik. Banyak syarikat akan menggunakan perisian keselamatan untuk memastikan keselamatan rangkaian dalaman. …

Pemprosesan pemetaan medan dalam dok sistem sering menemui masalah yang sukar ketika melaksanakan sistem dok: bagaimana untuk memetakan medan antara muka sistem dengan berkesan ...

Apabila menggunakan Mybatis-Plus atau Rangka Kerja ORM yang lain untuk operasi pangkalan data, sering diperlukan untuk membina syarat pertanyaan berdasarkan nama atribut kelas entiti. Sekiranya anda secara manual setiap kali ...

Mula musim bunga menggunakan versi IntelliJideaultimate ...

Penyelesaian untuk menukar nama kepada nombor untuk melaksanakan penyortiran dalam banyak senario aplikasi, pengguna mungkin perlu menyusun kumpulan, terutama dalam satu ...

Penukaran objek dan tatasusunan Java: Perbincangan mendalam tentang risiko dan kaedah penukaran jenis cast yang betul Banyak pemula Java akan menemui penukaran objek ke dalam array ...

Apabila menggunakan tkmybatis untuk pertanyaan pangkalan data, bagaimana dengan anggun mendapatkan nama pembolehubah kelas entiti untuk membina keadaan pertanyaan adalah masalah biasa. Artikel ini akan ...

Memahami rawak kebergantungan bulat dalam permulaan projek musim bunga. Semasa membangunkan projek musim bunga, anda mungkin menghadapi rawak yang disebabkan oleh kebergantungan bulat pada permulaan projek ...
