注意:本篇文章是本人閱讀關于Android動畫的文章所寫下的總結,方便以后查閱,所有內容非原創,侵權刪。
本篇文章內容來自于
- Android高級進階 顧浩鑫
- Android自定義控件三部曲文章索引之動畫篇
目錄
4.屬性動畫PropertyAnimation(基類Animator)
--4.2 ObjectAnimator(ValueAnimator的子類 實際開發中最常用)
----4.2.1 ObjectAnimator構造方法(5種)
----4.2.2 ObjectAnimator代碼實現
------4.2.2.1 ofInt ofFloat ofObject構造
------4.2.2.2 ofPropertyValuesHolder構造
----4.2.3 ObjectAnimator動畫原理
----4.2.4 ObjectAnimator XML實現
4.屬性動畫PropertyAnimation(基類Animator)
一個完整的屬性動畫由兩部分組成:
1.計算動畫各個幀的相關屬性值
2.將這些屬性值設置給指定的對象
4.2 ObjectAnimator(ValueAnimator的子類 實際開發中最常用)
是ValueAnimator的子類,封裝實現了第二部分功能。
實際開發用到的更多的是ObjectAnimator,只有在ObjectAnimator實現不了的情景下,才考慮使用ValueAnimator
4.2.1 ObjectAnimator構造方法
由于ObjectAnimator是派生自ValueAnimator的,所以ValueAnimator中所能使用的方法,在ObjectAnimator中都可以正常使用。
但ObjectAnimator也重寫了幾個方法,比如ofInt(),ofFloat()等。
public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
public static ObjectAnimator ofArgb(Object target, String propertyName, int... values)
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
4.2.2 ObjectAnimator代碼實現
4.2.2.1 ofInt ofFloat ofObject
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "rotation", 0,180,0);
objectAnimator.setDuration(3000);
objectAnimator.start();
ObjectAnimator做動畫,并不是根據控件xml中的屬性來改變的,而是通過指定屬性所對應的set方法來改變的。
比如,我們上面指定的改變rotation的屬性值,ObjectAnimator在做動畫時就會到指定控件(TextView)中去找對應的setRotation()方法來改變控件中對應的值。
在View中有關動畫,總共有下面幾組set方法:
//1、透明度:alpha
public void setAlpha(float alpha)
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "alpha", 1, 0, 1);
//2、旋轉度數:rotation、rotationX、rotationY
public void setRotation(float rotation) 表示旋轉度數
public void setRotationX(float rotationX) 表示旋轉度數
public void setRotationY(float rotationY) 表示旋轉度數
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "rotation", 0,180,0);
//3、平移:translationX、translationY
public void setTranslationX(float translationX) 向右為正方向
public void setTranslationY(float translationY) 向下為正方向
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "translationX", 0, 200, -200,0);
//縮放:scaleX、scaleY
public void setScaleX(float scaleX) scaleX表示縮放倍數
public void setScaleY(float scaleY) scaleY表示縮放倍數
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "scaleX", 0, 3, 1);
使用時要注意
關于屬性的get方法
當且僅當我們在創建ObjectAnimator時,只給他傳遞了一個過渡值的時候,系統才會調用屬性對應的get函數來得到動畫的初始值!
4.2.2.2 ofPropertyValuesHolder
構造方法如下
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
4.2.2.2.1.什么是PropertyValuesHolder
PropertyValuesHolder這個類的意義就是,它其中保存了動畫過程中所需要操作的屬性和對應的值。
我們通過ofFloat(Object target, String propertyName, float… values)構造的動畫,ofFloat()的內部實現其實就是將傳進來的參數封裝成PropertyValuesHolder實例來保存動畫狀態。在封裝成PropertyValuesHolder實例以后,后期的各種操作也是以PropertyValuesHolder為主的。
ObjectAnimator給我們提供了一個口子,讓我們自己構造PropertyValuesHolder來構造動畫。
4.2.2.2.2 PropertyValuesHolder構造函數
public static PropertyValuesHolder ofFloat(String propertyName, float... values)
public static PropertyValuesHolder ofInt(String propertyName, int... values)
public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object... values)
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values)
4.2.2.2.2 PropertyValuesHolder常用方法
//設置動畫的Evaluator
public void setEvaluator(TypeEvaluator evaluator)
//用于設置ofFloat所對應的動畫值列表
public void setFloatValues(float... values)
//用于設置ofInt所對應的動畫值列表
public void setIntValues(int... values)
//用于設置ofKeyframe所對應的動畫值列表
public void setKeyframes(Keyframe... values)
//用于設置ofObject所對應的動畫值列表
public void setObjectValues(Object... values)
//設置動畫屬性名
public void setPropertyName(String propertyName)
setFloatValues(float… values)對應PropertyValuesHolder.ofFloat(),用于動態設置動畫中的數值。setIntValues、setKeyframes、setObjectValues同理;
setPropertyName用于設置PropertyValuesHolder所需要操作的動畫屬性名;
4.2.2.2.3 使用PropertyValuesHolder創建ObjectAnimator
1??ofFloat ofInt
PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);
PropertyValuesHolder backgroundColor = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(tvAnimPropertyObject, rotation, backgroundColor);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new AccelerateInterpolator());
objectAnimator.start();
2??ofObject
PropertyValuesHolder charText = PropertyValuesHolder.ofObject("CharText", new CharEvaluator(), new Character('A'), new Character('Z'));
ObjectAnimator objectAnimator1 = ObjectAnimator.ofPropertyValuesHolder(mtvAnimPropertyObject, charText);
objectAnimator1.setDuration(3000);
objectAnimator1.start();
3??ofKeyFrame
① 什么是keyFrame
如果要控制動畫速率的變化,我們可以通過自定義插值器,也可以通過自定義Evaluator來實現。但有一定的難度。為了解決方便的控制動畫速率的問題,谷歌定義了一個KeyFrame的類,也就是關鍵幀。
就是類似動畫中的關鍵幀:
比如我們要讓一個球在30秒時間內,從(0,0)點運動到(300,200)點,我們只需要定義兩個關鍵幀,在動畫開始時定義一個,把球的位置放在(0,0)點;在30秒后,再定義一個關鍵幀,把球的位置放在(300,200)點。在動畫 開始時,球初始在是(0,0)點,30秒時間內就adobe flash就會自動填充,把球平滑移動到第二個關鍵幀的位置(300,200)點;
一個關鍵幀必須包含兩個原素,第一時間點,第二位置。即這個關鍵幀是表示的是某個物體在哪個時間點應該在哪個位置上。
② KeyFrame 構造方法
// ofFloat
public static Keyframe ofFloat(float fraction)
public static Keyframe ofFloat(float fraction, float value)
//ofInt
public static Keyframe ofInt(float fraction)
public static Keyframe ofInt(float fraction, int value)
//ofObject
public static Keyframe ofObject(float fraction, Object value)
public static Keyframe ofObject(float fraction)
public static Keyframe ofFloat(float fraction, float value)
- fraction:表示當前的顯示進度,即從加速器中getInterpolation()函數的返回值;
- value:表示當前應該在的位置
Keyframe kf0 = Keyframe.ofFloat(0, 0);
Keyframe kf1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0);
比如Keyframe.ofFloat(0, 0)表示動畫進度為0時,動畫所在的數值位置為0;Keyframe.ofFloat(0.25f, -20f)表示動畫進度為25%時,動畫所在的數值位置為-20;Keyframe.ofFloat(1f,0)表示動畫結束時,動畫所在的數值位置為0;
public static Keyframe ofFloat(float fraction)
- 參數fraction,表示當前關鍵幀所在的動畫進度位置。
那在這個進度時所對應的值 用setValue來設置
③KeyFrame常用方法
//設置fraction參數,即Keyframe所對應的進度
public void setFraction(float fraction)
//設置當前Keyframe所對應的值
public void setValue(Object value)
//設置Keyframe動作期間所對應的插值器
public void setInterpolator(TimeInterpolator interpolator)
③ 代碼實現
1.使用ofFloat/ofInt構造KeyFrame
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe frame2 = Keyframe.ofFloat(1, 0);
PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("rotation", frame0, frame1, frame2);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofPropertyValuesHolder(tvAnimPropertyObject, propertyValuesHolder);
objectAnimator2.setDuration(3000);
objectAnimator2.start();
2.使用ofObject構造KeyFrame
Keyframe frame_0 = Keyframe.ofObject(0f, new Character('A'));
Keyframe frame_1 = Keyframe.ofObject(0.1f, new Character('L'));
Keyframe frame_2 = Keyframe.ofObject(1, new Character('Z'));
PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofKeyframe("CharText", frame_0, frame_1, frame_2);
propertyValuesHolder1.setEvaluator(new CharEvaluator());
ObjectAnimator objectAnimator3 = ObjectAnimator.ofPropertyValuesHolder(mtvAnimPropertyObject, propertyValuesHolder1);
objectAnimator3.setDuration(3000);
objectAnimator3.start();
④ 關于KeyFrame的插值器的注意點
關鍵幀可通過以下方法設置插值器
//設置Keyframe動作期間所對應的插值器
public void setInterpolator(TimeInterpolator interpolator)
如果給這個Keyframe設置上插值器,
那么這個插值器就是從上一個Keyframe開始到當前設置插值器的Keyframe時,這個過程值的計算是利用這個插值器的
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
frame1.setInterpolator(new BounceInterpolator());
在frame0到frame1的中間值計算過程中,就是用的就是回彈插值。
給Keyframe.ofFloat(0f, 0)設置插值器是無效的,因為它是第一幀。
⑤ 關于關鍵幀KeyFrame的注意點
如果去掉第0幀(fraction為0),將以第一個關鍵幀為起始位置
如果去掉結束幀(fraction為1),將以最后一個關鍵幀為結束位置
使用Keyframe來構建動畫,至少要有兩個或兩個以上幀,否則會崩
4.2.3 ObjectAnimator動畫原理
1??首先通過加速器產生當前進度的百分比,
然后再經過Evaluator生成對應百分比所對應的數字值。
這兩步與ValueAnimator是完全一樣的,
2??唯一不同的是最后一步
在ValueAnimator中,我們要通過添加監聽器來監聽當前數字值。
而在ObjectAnimator中,則是先根據屬性值拼裝成對應的set函數的名字,比如這里的scaleY的拼裝方法就是將屬性的第一個字母強制大寫后,與set拼接,所以就是setScaleY。然后通過反射找到對應控件的setScaleY(float scaleY)函數,將當前數字值做為setScaleY(float scale)的參數將其傳入。
3??調用完set方法,set方法內部會對控件進行設置,動畫在進行時每隔十幾毫秒會刷新一次,set函數也會每隔十幾毫秒會被調用一次(將動畫中間值傳給他)。
4.2.4 ObjectAnimator XML實現
標簽<objectAnimator />對應ObjectAnimator
4.2.4.1 <objectAnimator />標簽字段意義及使用方法
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]
android:interpolator=["@android:interpolator/XXX"]/>
android:propertyName:對應屬性名,即ObjectAnimator所需要操作的屬性名。
android:valueType:表示參數值類型,取值為intType和floatType;與android:valueFrom、android:valueTo相對應。
4.2.4.2 代碼實現
- res/animator新建animtor_object.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="TranslationY"
android:duration="2000"
android:valueFrom="0.0"
android:valueTo="400.0"
android:valueType="floatType"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatCount="1"
android:repeatMode="reverse"
android:startOffset="2000"
/>
- 加載動畫
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator_object);
animator.setTarget(tvAnimPropertyObject);
animator.start();