Android補間動畫和屬性動畫的區別及屬性動畫使用詳解


補間動畫和屬性動畫主要區別:

  • 作用對象不同,補間動畫只能作用在view上,屬性動畫可以作用在所有對象上。

  • 屬性變化不同,補間動畫只是改變顯示效果,不會改變view的屬性,比如位置、寬高等,而屬性動畫實際改變對象的屬性。

  • 動畫效果不同,補間動畫只能實現位移、縮放、旋轉和透明度四種動畫操作,而屬性動畫還能實現補間動畫所有效果及其他更多動畫效果。

新引入的屬性動畫機制已經不再是針對於 view 來設計的,也不限定於只能實現位移、縮放、旋轉和透明度這幾種動畫操作,同時也不再只是一種視覺上的動畫效果。它實際上是一種不斷地對值進行操作的機制,並將值賦值到指定對象的指定屬性上,可以是任意對象的任意屬性。我們只需要告訴系統動畫的運行時長,需要執行哪種類型的動畫,以及動畫的初始值和結束值,剩下的工作就可以全部交給系統去完成了。

ValueAnimator

ValueAnimator是整個屬性動畫機制當中最核心的一個類,前面我們已經提到了,屬性動畫的運行機制是通過不斷地對值進行操作來實現的,而初始值和結束值之間的動畫過渡就是由ValueAnimator這個類來負責計算的。它的內部使用一種時間循環的機制來計算值與值之間的動畫過渡,我們只需要將初始值和結束值提供給ValueAnimator,並且告訴它動畫所需運行的時長,那么ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。除此之外,ValueAnimator還負責管理動畫的播放次數、播放模式、以及對動畫設置監聽器等,確實是一個非常重要的類。

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
anim.setDuration( 300 );  
anim.start();

用法就是這么簡單,現在如果你運行一下上面的代碼,動畫就會執行了。可是這只是一個將值從0過渡到1的動畫,又看不到任何界面效果,我們怎樣才能知道這個動畫是不是已經真正運行了呢?這就需要借助監聽器來實現了,如下所示:

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
anim.setDuration( 300 );  
anim.addUpdateListener( new  ValueAnimator.AnimatorUpdateListener() {  
     @Override  
     public  void  onAnimationUpdate(ValueAnimator animation) {  
         float  currentValue = ( float ) animation.getAnimatedValue();  
         Log.d( "TAG" "cuurent value is "  + currentValue);  
     }  
});  
anim.start();

ObjectAnimator

相比於ValueAnimator,ObjectAnimator可能才是我們最常接觸到的類,因為ValueAnimator只不過是對值進行了一個平滑的動畫過渡,但我們實際使用到這種功能的場景好像並不多。而ObjectAnimator則就不同了,它是可以直接對任意對象的任意屬性進行動畫操作的,比如說View的alpha屬性。

不過雖說ObjectAnimator會更加常用一些,但是它其實是繼承自ValueAnimator的,底層的動畫實現機制也是基於ValueAnimator來完成的,因此ValueAnimator仍然是整個屬性動畫當中最核心的一個類。那么既然是繼承關系,說明ValueAnimator中可以使用的方法在ObjectAnimator中也是可以正常使用的,它們的用法也非常類似,這里如果我們想要將一個TextView在5秒中內從常規變換成全透明,再從全透明變換成常規,就可以這樣寫:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview,  "alpha" , 1f, 0f, 1f);
animator.setDuration( 5000 );
animator.start();

可以看到,我們還是調用了ofFloat()方法來去創建一個ObjectAnimator的實例,只不過ofFloat()方法當中接收的參數有點變化了。這里第一個參數要求傳入一個object對象,我們想要對哪個對象進行動畫操作就傳入什么,這里我傳入了一個textview。第二個參數是想要對該對象的哪個屬性進行動畫操作,由於我們想要改變TextView的不透明度,因此這里傳入"alpha"。后面的參數就是不固定長度了,想要完成什么樣的動畫就傳入什么值,這里傳入的值就表示將TextView從常規變換成全透明,再從全透明變換成常規。之后調用setDuration()方法來設置動畫的時長,然后調用start()方法啟動動畫。

到目前為止,ObjectAnimator的用法還算是相當簡單吧,但是我相信肯定會有不少朋友現在心里都有同樣一個疑問,就是ofFloat()方法的第二個參數到底可以傳哪些值呢?

  • translationX、translationY:這兩個屬性作為一種增量來控制着View對象從它布局容器的左上角坐標開始的位置。

  • rotation、rotationX、rotationY:這三個屬性控制着View對象圍繞它的支點進行2D和3D的旋轉。

  • scaleX和scaleY:這兩個屬性控制着View對象圍繞它的支點進行2D縮放。

  • pivotX和pivotY:這兩個屬性控制着View對象的支點位置,圍繞這個支點進行旋轉和縮放變換處理。默認情況下,該支點的位置就是View對象的中心點。

  • alpha:它表示View對象的alpha透明度。

  • x、y:這是兩個簡單的實用的屬性,它描述了View對象在它的容器中最終的位置。

以上只是view中常用的動畫操作,為什么會是這些勒?

其實ObjectAnimator內部的工作機制並不是直接對我們傳入的屬性名進行操作的,而是會去尋找這個屬性名對應的get和set方法。

比如第二個參數為alpha,那么該對象一定有setAlpha和getAlpha方法,而且 set方法參數為float類型,get方法返回值為float類型。使用Android Studio 開發時如果該值錯誤,不符合以上條件,會自動檢測提醒錯誤。

至於后面的參數含義可以查找對應的set方法來理解。比如ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f) 就是循環調用該對象的setAlpha方法。

動畫實踐

1、平移動畫代碼如下:

ObjectAnimator.ofFloat(view,  "translationX" , 0f, 200f)
.setDuration( 500 )
.start();

2、透明度動畫代碼如下:

ObjectAnimator.ofFloat(view,  "alpha" , 1f, 0f)
.setDuration( 1500 )
.start();

3、旋轉動畫代碼如下:

ObjectAnimator.ofFloat(view,  "scaleX" , 1f, 0f)
.setDuration( 1000 )
.start();

4、位移動畫代碼如下:

ObjectAnimator.ofFloat(view,  "translationX" 0 , view.getWidth())
.setDuration( 1000 )
.start();

5、背景顏色漸變代碼如下:

if  (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
     // API 必須代碼 23 才能使用ofArgb
     ObjectAnimator animator = ObjectAnimator.ofArgb(view,  "backgroundColor" 0xffff00ff 0xffffff00 0xffff00ff );
     animator.setDuration( 4000 );
     animator.start();
}

6、組合動畫-----伸縮、透明度動畫同時開始代碼如下:

AnimatorSet animatorSet =  new  AnimatorSet(); //組合動畫
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view,  "scaleX" , 1f, 0f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view,  "scaleY" , 1f, 0f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(view,  "alpha" , 1f, 0f);
 
animatorSet.setDuration( 2000 );
animatorSet.setInterpolator( new  DecelerateInterpolator());
animatorSet.play(scaleX).with(scaleY).with(alpha); //動畫同時開始
animatorSet.start();

7、組合動畫-----縮放、透明度動畫先后開始代碼如下:

AnimatorSet animatorSet =  new  AnimatorSet(); //組合動畫
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view,  "scaleX" , 1f, 2f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view,  "scaleY" , 1f, 2f);
ObjectAnimator alpha = ObjectAnimator.ofFloat(view,  "alpha" , 1f, 0f);
ObjectAnimator scaleX2 = ObjectAnimator.ofFloat(view,  "scaleX" , 2f, 0f);
ObjectAnimator scaleY2 = ObjectAnimator.ofFloat(view,  "scaleY" , 2f, 0f);
 
animatorSet.setDuration( 2000 );
animatorSet.setInterpolator( new  DecelerateInterpolator());
animatorSet.play(scaleX).with(scaleY).before(alpha).before(scaleX2).before(scaleY2); //alpha 動畫后執行
animatorSet.start();

  • after(Animator anim) :將現有動畫插入到傳入的動畫之后執行

  • after(long delay) :將現有動畫延遲指定毫秒后執行

  • before(Animator anim): 將現有動畫插入到傳入的動畫之前執行

  • with(Animator anim) :將現有動畫和傳入的動畫同時執行

在動畫執行前,還可以為動畫添加監聽事件

animatorSet.addListener( new  Animator.AnimatorListener() {
     @Override
     public  void  onAnimationStart(Animator animation) {
         //動畫開始的時候調用
     }
 
     @Override
     public  void  onAnimationEnd(Animator animation) {
         //畫結束的時候調用
     }
 
     @Override
     public  void  onAnimationCancel(Animator animation) {
         //動畫被取消的時候調用
     }
 
     @Override
     public  void  onAnimationRepeat(Animator animation) {
         //動畫重復執行的時候調用
     }
});

有時候,我們只想監聽其中的某個事件,其他的我們並不關心。官方還是很人性化得為我們提供了另一個類:AnimatorListenerAdapter,在這個類中,只要重寫我們想要的監聽事件就可以了。

animatorSet.addListener( new  AnimatorListenerAdapter() {
     @Override
     public  void  onAnimationStart(Animator animation) {
 
     }
});

8、按鈕控件寬度增加動畫代碼如下:

ObjectAnimator animator = ObjectAnimator.ofInt(v,  "width" , v.getWidth(), v.getWidth() *  2 );
animator.setDuration( 1000 );
animator.start();

9、拋物線動畫代碼如下:

ValueAnimator valueAnimator =  new  ValueAnimator();
valueAnimator.setDuration( 1500 );
valueAnimator.setObjectValues( new  PointF( 0 100 ));
valueAnimator.setInterpolator( new  LinearInterpolator());
valueAnimator.setEvaluator( new  TypeEvaluator<PointF>() {
 
     @Override
     public  PointF evaluate( float  fraction, PointF startValue, PointF endValue) {
         /**x方向200px/s ,則y方向0.5 * 200 * t**/
         PointF point =  new  PointF();
         point.x =  200  * fraction *  3 ;
         point.y =  0 .5f *  200  * (fraction *  3 ) * (fraction *  3 );
         return  point;
     }
});
valueAnimator.start();
valueAnimator.addUpdateListener( new  ValueAnimator.AnimatorUpdateListener() {
     @Override
     public  void  onAnimationUpdate(ValueAnimator animation) {
         PointF point = (PointF) animation.getAnimatedValue();
         v.setX(point.x);
         v.setY(point.y);
     }
});


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM