Android樣式的開發:Property Animation篇

發表於2015-11-30

Android專案重構之路:架構篇

Android專案重構之路:介面篇

Android專案重構之路:實現篇

Android技術積累:開發規範

Android樣式的開發:shape篇

Android樣式的開發:selector篇

Android樣式的開發:layer-list篇

Android樣式的開發:drawable彙總篇

Android樣式的開發:View Animation篇

 

前篇文章說過,Android框架還提供了兩種動畫體系,前一篇已經總結了檢視動畫(View Animation)的用法,本篇則接著總結另一種動畫體系——屬性動畫(Property Animation)的用法。

檢視動畫只能作用於View,而且檢視動畫改變的只是View的繪製效果,View真正的屬性並沒有改變。比如,一個按鈕做平移的動畫,雖然按鈕的確做了平移,但按鈕可點選的區域並沒隨著平移而改變,還是在原來的位置。而屬性動畫則可以改變真正的屬性,從而實現按鈕平移時點選區域也跟著平移。通俗點說,屬性動畫其實就是在一定時間內,按照一定規律來改變物件的屬性,從而使物件展現出動畫效果。

屬性動畫是在android 3.0引入的動畫體系,如果還想適配基本已經滅絕的2.x版本,只好繞道了。
屬性動畫和檢視動畫一樣,可以通過xml檔案定義,不同的是,檢視動畫的xml檔案放於res/anim/目錄下,而屬性動畫的xml檔案則放於res/animator/目錄下。一個是anim,一個是animator,別搞錯了。同樣的,在Java程式碼裡引用屬性動畫的xml檔案時,則用R.animator.filename,不同於檢視動畫,引用時為R.anim.filename

屬性動畫主要有三個元素:<animator><objectAnimator><set>
相對應的有三個類:ValueAnimatorObjectAnimatorAnimatorSet
ValueAnimator是基本的動畫類,處理值動畫,通過監聽某一值的變化,進行相應的操作。ObjectAnimatorValueAnimator的子類,處理物件動畫。AnimatorSet則為動畫集,可以組合另外兩種動畫或動畫集。相應的三個標籤元素的關係也一樣。
樣式開發主要還是用xml的形式,所以這裡主要還是講標籤的用法。

<animator>

<animator>標籤與對應的ValueAnimator類提供了屬性動畫的核心功能,包括計算動畫值、動畫時間細節、是否重複等。執行屬性動畫分兩個步驟:

  1. 計算動畫值
  2. 將動畫值應用到物件和屬性上

ValuAnimiator只完成第一步,即只計算值,要實現第二步則需要在值變化的監聽器裡自行更新物件屬性。
通過<animator>標籤可以很方便的對ValuAnimiator進行設定,可設定的屬性如下:

  • android:duration 動畫從開始到結束持續的時長,單位為毫秒
  • android:startOffset 設定動畫執行之前的等待時長,單位為毫秒
  • android:repeatCount 設定動畫重複執行的次數,預設為0,即不重複;可設為-1或infinite,表示無限重複
  • android:repeatMode 設定動畫重複執行的模式,可設為以下兩個值其中之一:
    • restart 動畫重複執行時從起點開始,預設為該值
    • reverse 動畫會反方向執行
  • android:valueFrom 動畫開始的值,可以為int值、float值或color值
  • android:valueTo 動畫結束的值,可以為int值、float值或color值
  • android:valueType 動畫值型別,若為color值,則無需設定該屬性
    • intType 指定動畫值,即以上兩個value屬性的值為整型
    • floatType 指定動畫值,即以上兩個value屬性的值為浮點型,預設值
  • android:interpolator 設定動畫速率的變化,比如加速、減速、勻速等,需要指定Interpolator資源。具體用法在View Animation篇已經講過,這裡不再重複

接著,用一個例項講解具體的用法吧。在這個例子裡,將一個按鈕的寬度進行縮放,從100%縮放到20%。
xml檔案的程式碼如下:

可看到,值的變化從100到20,動畫時長3000毫秒,以下則是目標按鈕的xml程式碼:

按鈕預設是填充螢幕寬度的,點選時的執行方法為onScaleWidth,以下則是onScaleWidth方法的程式碼:

View Animation篇中已經知道,檢視動畫是通過AnimationUtils類的loadAnimation()方法獲取xml檔案相對應的Animation類例項,而屬性動畫則是通過AnimatorInflater類的loadAnimation()方法獲取相應的Animator類例項。
另外,ValueAnimator通過新增AnimatorUpdateListener監聽器監聽值的變化,從而再手動更新目標物件的屬性。
最後,通過呼叫valueAnimator.start()方法啟動動畫。

<objectAnimator>

<objectAnimator>標籤對應的類為ObjectAnimator,為ValueAnimator的子類。<objectAnimator>標籤與<animator>標籤不同的是,<objectAnimator>可以直接指定動畫的目標物件的屬性。標籤可設定的屬性除了和<animator>一樣的那些,另外多了一個:

  • android:propertyName 目標物件的屬性名,要求目標物件必須提供該屬性的setter方法,如果動畫的時候沒有初始值,還需要提供getter方法

還是用例項說明具體用法,還是用上面的例子,將一個按鈕的寬度進行縮放,從100%縮放到20%,但這次改用<objectAnimator>實現。
以下為xml檔案的程式碼:

<animator>的例子相比,就只是多了一個android:propertyName的屬性,設定值為width。也就是說,動畫改變的屬性為width,值將從100逐漸減到20。另外,值是從setWidth()傳遞過去的,再從getWidth()獲取。而且,這裡設定的值代表的是比例值,因此,還需要進行計算轉化為實際的寬度值。最後,物件實際的寬度值為view.getLayoutParams().width。因此,我將用一個包裝類來包裝原始的view物件,對其提供setWidth()和getWidth()方法,程式碼如下:

上面setWidth()的程式碼裡,根據比例值轉化為了實際的寬度值。最後,動畫處理的程式碼如下:

ObjectAnimator提供了屬性的設定,但相應的需要有該屬性的setter和getter方法。而ValueAnimator則只是定義了值的變化,並不指定目標屬性,所以也不需要提供setter和getter方法,但只能在AnimatorUpdateListener監聽器裡手動更新屬性。不過,也因為沒有指定屬性,所以其實更具靈活性了,你可以在監聽器里根據值的變化做任何事情,比如更新多個屬性,比如在縮放寬度的同時做垂直移動。

為了對View更方便的設定屬性動畫,Android系統也提供了View的一些屬性和相應的setter和getter方法:

  • alpha:透明度,預設為1,表示不透明,0表示完全透明
  • pivotX 和 pivotY:旋轉的軸點和縮放的基準點,預設是View的中心點
  • scaleX 和 scaleY:基於pivotX和pivotY的縮放,1表示無縮放,小於1表示收縮,大於1則放大
  • rotationrotationX 和 rotationY:基於軸點(pivotX和pivotY)的旋轉,rotation為平面的旋轉,rotationX和rotationY為立體的旋轉
  • translationX 和 translationY:View的螢幕位置座標變化量,以layout容器的左上角為座標原點
  • x 和 y:View在父容器內的最終位置,是左上角座標和偏移量(translationX,translationY)的和

<set>

<set>標籤對應於AnimatorSet類,可以將多個動畫組合成一個動畫集,如上面提到的在縮放寬度的同時做垂直移動,可以將一個縮放寬度的動畫和一個垂直移動的動畫組合在一起。
<set>標籤有一個屬性可以設定動畫的時序關係:

  • android:ordering 設定動畫的時序關係,取值可為以下兩個值之一:
    • together 動畫同時執行,預設值
    • sequentially 動畫按順序執行

那如果想有些動畫同時執行,有些按順序執行,該怎麼辦呢?因為<set>標籤是可以巢狀其他<set>標籤的,也就是說可以將同時執行的組合在一個<set>標籤,再嵌在按順序執行的<set>標籤內。

看例項程式碼吧,以下為xml檔案:

以上程式碼可實現兩個同時執行的動畫,一個將width從100縮放到20,一個將marginTop從0增加到100。多了一個marginTop屬性,那麼,在ViewWrapper新增setMarginTop()方法,新增後的ViewWrapper類程式碼如下:

最後,動畫處理的程式碼:

這樣就搞定了,實現了寬度縮放和垂直移動的效果。

寫在最後

至此,檢視動畫和屬性動畫基本的用法都總結完了。示例程式碼可從github上檢視,github地址:
https://github.com/keeganlee/kstyle.git

相關文章