自定義控制元件ObjectAnimator基本使用
利用ObjectAnimator重寫的ofFloat方法如何實現一個動畫:
(改變透明度)
- publicstatic ObjectAnimator ofFloat(Object target, String propertyName, float... values)
- 第一個引數用於指定這個動畫要操作的是哪個控制元件
- 第二個引數用於指定這個動畫要操作這個控制元件的哪個屬性
- 第三個引數是可變長引數,這個就跟ValueAnimator中的可變長引數的意義一樣了,就是指這個屬性值是從哪變到哪。像我們上面的程式碼中指定的就是將textview的alpha屬性從0變到1再變到0;
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);
- animator.setDuration(2000);
- animator.start();
從程式碼中可以看到,我們只需要改變ofFloat()的第二個引數的值就可以實現對應的動畫;
那麼問題來了,我們怎麼知道第二個引數的值是啥呢?
2、setter函式
我們再回來看構造改變rotation值的ObjectAnimator的方法-
ObjectAnimator animator = ObjectAnimator.ofFloat(tv,
- //1、透明度:alpha
- publicvoid setAlpha(float alpha)
- //2、旋轉度數:rotation、rotationX、rotationY
- publicvoid setRotation(float rotation)
- publicvoid setRotationX(float rotationX)
- publicvoid setRotationY(float rotationY)
- //3、平移:translationX、translationY
- publicvoid setTranslationX(float translationX)
- publicvoid setTranslationY(float translationY)
- //縮放:scaleX、scaleY
- publicvoid setScaleX(float scaleX)
- publicvoid setScaleY(float scaleY)
在開始逐個看這些函式的使用方法前,我們先做一個總結:
1、要使用ObjectAnimator來構造對畫,要操作的控制元件中,必須存在對應的屬性的set方法
2、setter 方法的命名必須以駱駝拼寫法命名,即set後每個單詞首字母大寫,其餘字母小寫,即類似於setPropertyName所對應的屬性為propertyName
下面我們就來看一下上面中各個方法的使用方法及作用。
有關alpha的用法,上面已經講過了,下面我們來看看其它的
(1)、setRotationX、setRotationY與setRotation
- setRotationX(float rotationX):表示圍繞X軸旋轉,rotationX表示旋轉度數
- setRotationY(rotationY):表示圍繞Y軸旋轉,rotationY表示旋轉度數
- setRotation(float rotation):表示圍繞Z旋轉,rotation表示旋轉度數
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0);
- animator.setDuration(2000);
- animator.start();
效果圖如下:
從效果圖中明顯看出,textview的旋轉方法是圍繞X軸旋轉的,我們設定為從0度旋轉到270度再返回0度。
然後再來看看setRotationY的使用方法與效果:
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0);
- animator.setDuration(2000);
- animator.start();
效果圖如下:
從效果圖中明顯可以看出圍繞Y軸旋轉的。
我們再來看看setRotation的用法與效果:
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,270,0);
- animator.setDuration(2000);
- animator.start();
我們上面說了,setRotation是圍繞Z軸旋轉的,可能有些同學不理解什麼是Z軸,我們來看一張圖:
從這張圖中,綠色框部分表示手機螢幕,很明顯可以看出Z軸就是從螢幕左上角原點向外伸出的一條軸。這樣,我們也就可以理解圍繞Z軸旋轉,為什麼是這樣子轉了。
(2)、setTranslationX與setTranslationY
- setTranslationX(float translationX) :表示在X軸上的平移距離,以當前控制元件為原點,向右為正方向,引數translationX表示移動的距離。
- setTranslationY(float translationY) :表示在Y軸上的平移距離,以當前控制元件為原點,向下為正方向,引數translationY表示移動的距離。
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200, -200,0);
- animator.setDuration(2000);
- animator.start();
所以,我們上面在構造動畫時,指定的移動距離是(0, 200, -200,0),所以控制元件會從自身所有位置向右移動200畫素,然後再移動到距離原點-200的位置,最後回到原點;
然後我們來看看setTranslateY的用法:
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200, -100,0);
- animator.setDuration(2000);
- animator.start();
同樣,移動位置的座標也都是以當前控制元件所在位置為中心點的。所以對應的移動位置從原點移動向下移動200畫素,然後再移動到向下到距原點200畫素的位置,最後再回到(0,0)從效果圖中很明顯可以看出來。
從上面可以看出:每次移動距離的計算都是以原點為中心的;比如初始動畫為ObjectAnimator.ofFloat(tv, “translationY”, 0, 200, -100,0)表示首先從0移動到正方向200的位置,然後再移動到負方向100的位置,最後移動到原點。
(3)、setScaleX與setScaleY
- setScaleX(float scaleX):在X軸上縮放,scaleX表示縮放倍數
- setScaleY(float scaleY):在Y軸上縮放,scaleY表示縮放倍數
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1);
- animator.setDuration(2000);
- animator.start();
在效果圖中,從0倍放大到3倍,然後再還原到1倍的原始狀態。
然後再來看看setScaleY的用法
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
- animator.setDuration(2000);
- animator.start();
原始碼在文章底部給出 好了,到這裡有關View中自帶的set函式講完了,我們來看看ObjectAnimator是如何實現控制元件動畫效果的。
3、ObjectAnimator動畫原理
我們先來看張圖:
在這張圖中,將ValueAnimator的動畫流程與ObjectAnimator的動畫流程做了個對比。
可以看到ObjectAnimator的動畫流程中,也是首先通過加速器產生當前進度的百分比,然後再經過Evaluator生成對應百分比所對應的數字值。這兩步與ValueAnimator是完全一樣的,唯一不同的是最後一步,在ValueAnimator中,我們要通過新增監聽器來監聽當前數字值。而在ObjectAnimator中,則是先根據屬性值拼裝成對應的set函式的名字,比如這裡的scaleY的拼裝方法就是將屬性的第一個字母強制大寫後,與set拼接,所以就是setScaleY。然後通過反射找到對應控制元件的setScaleY(float
scaleY)函式,將當前數字值做為setScaleY(float scale)的引數將其傳入。
這裡在找到控制元件的set函式以後,是通過反射來呼叫這個函式的,有關反射的使用大家可以參考《夯實JAVA基本之二 —— 反射(1):基本類周邊資訊獲取》
這就是ObjectAnimator的流程,最後一步總結起來就是呼叫對應屬性的set方法,將動畫當前數字值做為引數傳進去。
根據上面的流程,這裡有幾個注意事項:
(1)、拼接set函式的方法:上面我們也說了是首先是強制將屬性的第一個字母大寫,然後與set拼接,就是對應的set函式的名字。注意,只是強制將屬性的第一個字母大寫,後面的部分是保持不變的。反過來,如果我們的函式名命名為setScalePointX(float ),那我們在寫屬性時可以寫成”scalePointX”或者寫成“ScalePointX”都是可以的,即第一個字母大小寫可以隨意,但後面的部分必須與set方法後的大小寫保持一致。
(2)、如何確定函式的引數型別:上面我們知道了如何找到對應的函式名,那對應的引數方法的引數型別如何確定呢?我們在講ValueAnimator的時候說過,動畫過程中產生的數字值與構造時傳入的值型別是一樣的。由於ObjectAnimator與ValueAnimator在插值器和Evaluator這兩步是完全一樣的,而當前動畫數值的產生是在Evaluator這一步產生的,所以ObjectAnimator的動畫中產生的數值型別也是與構造時的型別一樣的。那麼問題來了,像我們的構造方法。
- ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
那問題來了,如果沒有類似setScaleY(float xxx)的函式,我們只實現了一個setScaleY(int xxx)的函式怎麼辦?這裡雖然函式名一樣,但引數型別是不一樣的,那麼系統就會報一個錯誤:
意思就是對應函式的指定引數型別沒有找到。
(3)、呼叫set函式以後怎麼辦?從ObjectAnimator的流程可以看到,ObjectAnimator只負責把動畫過程中的數值傳到對應屬性的set函式中就結束了,注意傳給set函式以後就結束了!set函式就相當我們在ValueAnimator中新增的監聽的作用,set函式中的對控制元件的操作還是需要我們自己來寫的。
那我們來看看View中的setScaleY是怎麼實現的吧:
- /**