你們在使用APP的時候,有的APP在點擊語音搜索界面後,會出現一個小話筒,小話筒會相似雷達似得在閃爍,表示正在傾聽你說話的內容(這個你們能夠參照微軟的必應APP),那麼問題來了,這種動畫效果是如何實現的呢?其實實現這種動畫效果有不少種方法,最多見的是兩種:第一種就是插入n張圖片進行切換已達到如此目的,第二種就是經過改變一張圖片的透明度來達到閃爍的效果。下面就分別講一下經過這兩種方法如何實現。java
第一種:經過n張圖片之間切換實現動畫效果android
這種方法的原理很簡單,利用handler的延時機制在子線程中完成圖片切換,再在主線程展現。app
一、首先咱們要先寫一個線程池,在使用的時候方便調用。ide
1 package com.jereh.musicapplication.threadpool; 2 3 import java.util.concurrent.ExecutorService; 4 import java.util.concurrent.Executors; 5 import java.util.concurrent.ScheduledExecutorService; 6 7 /** 8 * Created by zhangdi on 2016/9/1. 9 * 這是一個線程池的工具類,在用到線程的時候能夠直接類名加方法名使用 10 */ 11 public class ThreadPoolManager { 12 /** 線程執行器 **/ 13 private static ExecutorService executorService = null; 14 /** 固定5個線程 **/ 15 private static int nThreads = 5; 16 /** 單例 **/ 17 private static ThreadPoolManager taskExecutorPool = null; 18 19 20 21 /** 初始化線程池 **/ 22 static { 23 taskExecutorPool = new ThreadPoolManager(nThreads * getNumCores()); 24 } 25 26 /** 構造函數 **/ 27 private ThreadPoolManager(int threads) { 28 //executorService = Executors.newFixedThreadPool(threads); 29 executorService = Executors.newScheduledThreadPool(threads); 30 } 31 32 /** 33 * 取得單例 34 * 35 * @return 36 */ 37 public static ThreadPoolManager getInstance() { 38 return taskExecutorPool; 39 } 40 41 /** 42 * 取得線程執行器 43 * 44 * @return 45 */ 46 public ExecutorService getExecutorService() { 47 return executorService; 48 } 49 50 /** 51 * 取得週期性線程執行器 52 * @return 53 */ 54 public ScheduledExecutorService getScheduledExcutorService(){ 55 return (ScheduledExecutorService)executorService; 56 } 57 58 /** 59 * 得到手機cup個數 60 * @return 61 */ 62 public static int getNumCores() { 63 int threadCount = Runtime.getRuntime().availableProcessors(); 64 return threadCount; 65 } 66 67 }
二、下一步就是在xml文件中插入一個佈局函數
1 <FrameLayout 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:id="@+id/fl"/>
三、而後就是在java代碼中編輯切換圖片了:工具
1 package com.jereh.musicapplication; 2 3 import android.graphics.drawable.Drawable; 4 import android.os.Message; 5 import android.support.v7.app.AppCompatActivity; 6 import android.os.Bundle; 7 import android.widget.FrameLayout; 8 9 import com.jereh.musicapplication.threadpool.ThreadPoolManager; 10 11 import java.util.Timer; 12 import java.util.TimerTask; 13 import java.util.concurrent.TimeUnit; 14 15 public class FrameActivity extends AppCompatActivity { 16 17 private Timer timer; 18 FrameLayout frameLayout; 19 Drawable drawable; 20 android.os.Handler handler = new android.os.Handler(){ 21 int i = 0; 22 @Override 23 public void handleMessage(Message msg) { 24 if (msg.what==1){ 25 i++; 26 move(i%4); 27 } 28 super.handleMessage(msg); 29 } 30 }; 31 void move(int i){ 32 drawable = getResources().getDrawable(R.mipmap.ic_launcher,null); 33 Drawable drawable1 = getResources().getDrawable(R.mipmap.dd1,null); 34 Drawable drawable2 = getResources().getDrawable(R.mipmap.dd2,null); 35 Drawable drawable3 = getResources().getDrawable(R.mipmap.dd3,null); 36 switch (i){ 37 case 0: 38 frameLayout.setForeground(drawable); 39 break; 40 case 1: 41 frameLayout.setForeground(drawable1); 42 break; 43 case 2: 44 frameLayout.setForeground(drawable2); 45 break; 46 case 3: 47 frameLayout.setForeground(drawable3); 48 break; 49 } 50 } 51 @Override 52 protected void onCreate(Bundle savedInstanceState) { 53 super.onCreate(savedInstanceState); 54 setContentView(R.layout.activity_frame); 55 frameLayout = (FrameLayout)findViewById(R.id.fl); 56 timer = new Timer(); 57 // timer.schedule(new TimerTask() { 58 // @Override 59 // public void run() { 60 // handler.sendEmptyMessage(1); 61 // } 62 // },0,500);//第二個參數是隔多少秒以後開始顯示,第三個是隔多久顯示下一個 63 64 ThreadPoolManager 65 .getInstance() 66 .getScheduledExcutorService() 67 .scheduleAtFixedRate(new Runnable() { 68 @Override 69 public void run() { 70 handler.sendEmptyMessage(1); 71 } 72 },0,500, TimeUnit.MILLISECONDS);//第二個參數是隔多少秒以後開始顯示,第三個是隔多久顯示下一個 73 } 74 75 76 @Override 77 protected void onDestroy() { 78 timer.cancel(); 79 super.onDestroy(); 80 81 } 82 }
這裏我寫了兩種方式,第一種是用Timer類來實現,後來發現使用自定義的線程池更好,你們若是不想在定義一個線程池的話,能夠直接使用Timer類來實現一樣的效果,至此使用第一種級n張圖片切換實現動畫效果的代碼就完成了。這種方式有一個弊端就是得須要n張圖片,那麼要是隻有單張圖片又該怎麼辦呢,那麼就可使用下面這種方法了。佈局
第二種:經過改變圖片透明度實現動畫效果學習
一、首先咱們先封裝兩個動畫方法,第一個是從不透明到徹底透明,第二個是徹底透明到不透明動畫
1 /** 2 * 透明效果 3 * @return 4 */ 5 public Animation getAlphaAnimationIn() { 6 //實例化 AlphaAnimation 主要是改變透明度 7 //透明度 從 1-不透明 0-徹底透明 8 Animation animation = new AlphaAnimation(1.0f, 0); 9 //設置動畫插值器 被用來修飾動畫效果,定義動畫的變化率 10 animation.setInterpolator(new DecelerateInterpolator()); 11 //設置動畫執行時間 12 animation.setDuration(2000); 13 return animation; 14 } 15 public Animation getAlphaAnimationOut() { 16 //實例化 AlphaAnimation 主要是改變透明度 17 //透明度 從 1-不透明 0-徹底透明 18 Animation animation = new AlphaAnimation(0, 1.0f); 19 //設置動畫插值器 被用來修飾動畫效果,定義動畫的變化率 20 animation.setInterpolator(new DecelerateInterpolator()); 21 //設置動畫執行時間 22 animation.setDuration(2000); 23 return animation; 24 }
二、分別給這兩個方法設置監聽,即第一個動畫完成馬上執行第二個動畫,第二個動畫完成在馬上執行第一個動畫以實現動畫循環播放的效果spa
1 voiceState1.setAnimation(animationIn); 2 voiceState1.setAnimation(animationOut); 3 /** 4 * 監聽動畫實現動畫間的切換 5 */ 6 animationOut.setAnimationListener(new Animation.AnimationListener() { 7 @Override 8 public void onAnimationStart(Animation animation) { 9 10 } 11 12 @Override 13 public void onAnimationEnd(Animation animation) { 14 voiceState1.startAnimation(animationIn); 15 } 16 17 @Override 18 public void onAnimationRepeat(Animation animation) { 19 20 } 21 }); 22 animationIn.setAnimationListener(new Animation.AnimationListener() { 23 @Override 24 public void onAnimationStart(Animation animation) { 25 26 } 27 28 @Override 29 public void onAnimationEnd(Animation animation) { 30 voiceState1.startAnimation(animationOut); 31 } 32 33 @Override 34 public void onAnimationRepeat(Animation animation) { 35 36 } 37 });
至此使用一張圖片經過改變其透明度實現閃爍效果就完成了。
這兩種方法在實現動畫閃爍效果方面都很實用,但願能給你們的學習有所幫助,若是您感受這篇文章還不錯,就給推薦一下吧,如果哪一個地方感受筆者寫的很差,也但願你們可以評論指正,謝謝!