會用就好——Android 有關動畫的一些小細節

前言

最適合的才是最好的,這里和大家分享下動畫使用中的一些細節,還有一兩個例子來綜合一下,其實這個內容是很基礎的,原諒筆者實在沒空,沒有為了本文去單獨寫一個demo,更沒有做GIF來演示,本文僅是作為備忘,有不準確的地方,歡迎大家指出,筆者及時改正,共同學習。

Part1

ObjectAnimator動畫是常常會被初學者忽視的一類動畫,估計和當下太多的貝塞爾曲線有關,筆者剛剛進入團隊的時候發現,很多絢麗的動畫其實并沒有用到很高級的東西,團隊的程序員老鳥表示ObjectAnimator就夠了,而且效果蠻好。

1、基礎

大多數動畫由透明度動畫(alpha)、平移動畫(translate)、縮放動畫(scale)、旋轉動畫(rotate)組成,這四個在開發中最常使用,其實也是夠用了,很多復雜的動畫可以拆分為簡單的動畫加以實現,用幾句代碼即可完成:

ObjectAnimator view_ani = ObjectAnimator.ofFloat(view, "alpha", 0, 1);

第一個參數是需要進行動畫操作的對象,比如一個ImageView
第二個參數是動畫的類別,這里進行透明度變化操作,所以是"alpha"
第三、第四個是動畫操作的范圍,這里指透明度為0到透明度100%
其他的動畫大多這個格式

ObjectAnimator logo_zoom_ani = ObjectAnimator.ofFloat(logoZoom, "translationY", -ScreenUtil.dip2px(this, 140));

 ObjectAnimator bgView_ani1 = ObjectAnimator.ofFloat(bgView, "scaleX", 1.0f, 1.5f);

 ObjectAnimator bgView_ani2 = ObjectAnimator.ofFloat(bgView, "scaleY", 1.0f, 1.5f);

上面有幾個需要注意的地方,第一是平移和縮放是有方向的,所以在代碼中要指定translationX、translationY還有scaleX、scaleY。其次就是對于平移動畫,要想到適配的問題,筆者用工具類把px轉dp。

2、一個例子

寫一個綜合的例子吧,比如要完成一個背景縮放且透明度漸變,與此同時,Logo在上滑的動畫,那么下面的代碼或許對你有幫助:

DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();

 AnimatorSet set = new AnimatorSet();

 // 背景縮放動畫

 ObjectAnimator bgView_ani0 = ObjectAnimator.ofFloat(bgView, "alpha", 0, 1);

 ObjectAnimator bgView_ani1 = ObjectAnimator.ofFloat(bgView, "scaleX", 1.0f, 1.5f);

 ObjectAnimator bgView_ani2 = ObjectAnimator.ofFloat(bgView, "scaleY", 1.0f, 1.5f);

// logo、slogan區域動畫
 ObjectAnimator logo_zoom_ani = ObjectAnimator.ofFloat(logoZoom, "translationY", -ScreenUtil.dip2px(this, 140));

 bgView_ani0.setInterpolator(decelerateInterpolator);

 bgView_ani1.setInterpolator(decelerateInterpolator);

 bgView_ani2.setInterpolator(decelerateInterpolator);

logo_zoom_ani.setInterpolator(decelerateInterpolator);

 bgView_ani0.setDuration(1500);

 bgView_ani1.setDuration(12000);

 bgView_ani2.setDuration(12000);

logo_zoom_ani.setDuration(1000).setStartDelay(1500);

 set.playTogether(bgView_ani0, bgView_ani1, bgView_ani2,logo_zoom_ani);

 set.start();

Part2

1、基礎

這里先說說AnimatorSet AnimationSet 的區別,AnimatorSet 和 AnimationSet 都是動畫集合,Animation 是針對視圖外觀的動畫實現,動畫被應用時外觀改變但視圖的觸發點不會發生變化,還是在原來定義的位置。Animator 是針對視圖屬性的動畫實現,動畫被應用時對象屬性產生變化,最終導致視圖外觀變化。

2、一個例子

AnimatorSet的內容大概就是上面那么多,下面用一個心跳動畫來闡述AnimationSet,先上代碼:

private void playHeartbeatAnimation() {

 AnimationSet swellAnimationSet = new AnimationSet(true);

 swellAnimationSet.addAnimation(new ScaleAnimation(1.0f, 1.13f, 1.0f, 1.13f, Animation.RELATIVE_TO_SELF, 0.5f,

 Animation.RELATIVE_TO_SELF, 0.5f));

swellAnimationSet.addAnimation(new AlphaAnimation(1.0f, 0.3f));

 

 swellAnimationSet.setDuration(1000);

 swellAnimationSet.setInterpolator(new AccelerateInterpolator());

 swellAnimationSet.setFillAfter(true);

 

 swellAnimationSet.setAnimationListener(new Animation.AnimationListener() {

 

 @Override

 public void onAnimationStart(Animation animation) {

 

 }

 

 @Override

 public void onAnimationRepeat(Animation animation) {

 }

 

 @Override

 public void onAnimationEnd(Animation animation) {

 AnimationSet shrinkAnimationSet = new AnimationSet(true);

 shrinkAnimationSet.addAnimation(new ScaleAnimation(1.13f, 1.0f, 1.13f, 1.0f, Animation.RELATIVE_TO_SELF,

 0.5f, Animation.RELATIVE_TO_SELF, 0.5f));

shrinkAnimationSet.addAnimation(new AlphaAnimation(0.3f, 1.0f));

 shrinkAnimationSet.setDuration(2000);

 shrinkAnimationSet.setInterpolator(new DecelerateInterpolator());

 shrinkAnimationSet.setFillAfter(false);

 goBtn.startAnimation(shrinkAnimationSet);// 動畫結束時重新開始,實現心跳的View

 }

 });

 

 goBtn.startAnimation(swellAnimationSet);

 }

代碼結構其實蠻簡單的,無非是一個放大動畫加一個縮小動畫,使用差值器修改下運行速度,大致的雛形就出來了,拿AlphaAnimation來說,參數和ObjectAnimator沒什么差別,大家可以試試看,效果其實還是可以的。

3、對例子的優化

很多項目中會開啟一個線程來操作一些循環的東西,那么同樣我們可以利用線程實現心跳動畫的持續。

 private class HeatbeatThread extends Thread {
 int anInt = 0;
 public void run() {
 while (true) {
 try {
 Thread.sleep(1000);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 runOnUiThread(new Runnable() {
 public void run() {
 //if (anInt < 2) {
 playHeartbeatAnimation();
 // anInt++;
 //}
 }
 });
 try {
 Thread.sleep(1500);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 }
 }
 ;
 }            

有時候我們需要手動去開啟和停止心跳,比如finish掉activity之前需要停止所有的動畫,否則就有可能造成內存泄漏等等,這里附上開啟和停止動畫的代碼:

/**

 * 開始心跳

 */

 private void startHeartBeat() {

 if (heartbeatThread == null) {

 heartbeatThread = new HeatbeatThread();

 }

 if (!heartbeatThread.isAlive()) {

 heartbeatThread.start();

 }

 }

/**

 * 停止心跳

 */

 private void stopHeartBeat() {

 if (heartbeatThread != null && heartbeatThread.isInterrupted()) {

 heartbeatThread.interrupt();

 heartbeatThread = null;

 System.gc();

 }

 }
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容