注意:本篇文章是本人閱讀關(guān)于Android動(dòng)畫的文章所寫下的總結(jié)葵腹,方便以后查閱琐脏,所有內(nèi)容非原創(chuàng),侵權(quán)刪坚嗜。
本篇文章內(nèi)容來自于
- Android高級(jí)進(jìn)階 顧浩鑫
- Android自定義控件三部曲文章索引之動(dòng)畫篇
目錄
4.屬性動(dòng)畫PropertyAnimation(基類Animator)
--4.2 ObjectAnimator(ValueAnimator的子類 實(shí)際開發(fā)中最常用)
----4.2.1 ObjectAnimator構(gòu)造方法(5種)
----4.2.2 ObjectAnimator代碼實(shí)現(xiàn)
------4.2.2.1 ofInt ofFloat ofObject構(gòu)造
------4.2.2.2 ofPropertyValuesHolder構(gòu)造
----4.2.3 ObjectAnimator動(dòng)畫原理
----4.2.4 ObjectAnimator XML實(shí)現(xiàn)
4.屬性動(dòng)畫PropertyAnimation(基類Animator)
一個(gè)完整的屬性動(dòng)畫由兩部分組成:
1.計(jì)算動(dòng)畫各個(gè)幀的相關(guān)屬性值
2.將這些屬性值設(shè)置給指定的對(duì)象
4.2 ObjectAnimator(ValueAnimator的子類 實(shí)際開發(fā)中最常用)
是ValueAnimator的子類,封裝實(shí)現(xiàn)了第二部分功能继蜡。
實(shí)際開發(fā)用到的更多的是ObjectAnimator回俐,只有在ObjectAnimator實(shí)現(xiàn)不了的情景下,才考慮使用ValueAnimator
4.2.1 ObjectAnimator構(gòu)造方法
由于ObjectAnimator是派生自ValueAnimator的稀并,所以ValueAnimator中所能使用的方法仅颇,在ObjectAnimator中都可以正常使用。
但ObjectAnimator也重寫了幾個(gè)方法碘举,比如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代碼實(shí)現(xiàn)
4.2.2.1 ofInt ofFloat ofObject
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "rotation", 0,180,0);
objectAnimator.setDuration(3000);
objectAnimator.start();
ObjectAnimator做動(dòng)畫,并不是根據(jù)控件xml中的屬性來改變的引颈,而是通過指定屬性所對(duì)應(yīng)的set方法來改變的耕皮。
比如,我們上面指定的改變r(jià)otation的屬性值蝙场,ObjectAnimator在做動(dòng)畫時(shí)就會(huì)到指定控件(TextView)中去找對(duì)應(yīng)的setRotation()方法來改變控件中對(duì)應(yīng)的值凌停。
在View中有關(guān)動(dòng)畫,總共有下面幾組set方法:
//1售滤、透明度:alpha
public void setAlpha(float alpha)
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "alpha", 1, 0, 1);
//2罚拟、旋轉(zhuǎn)度數(shù):rotation、rotationX、rotationY
public void setRotation(float rotation) 表示旋轉(zhuǎn)度數(shù)
public void setRotationX(float rotationX) 表示旋轉(zhuǎn)度數(shù)
public void setRotationY(float rotationY) 表示旋轉(zhuǎn)度數(shù)
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表示縮放倍數(shù)
public void setScaleY(float scaleY) scaleY表示縮放倍數(shù)
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tvAnimPropertyObject, "scaleX", 0, 3, 1);
使用時(shí)要注意
關(guān)于屬性的get方法
當(dāng)且僅當(dāng)我們?cè)趧?chuàng)建ObjectAnimator時(shí)秃励,只給他傳遞了一個(gè)過渡值的時(shí)候氏仗,系統(tǒng)才會(huì)調(diào)用屬性對(duì)應(yīng)的get函數(shù)來得到動(dòng)畫的初始值!
4.2.2.2 ofPropertyValuesHolder
構(gòu)造方法如下
public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
4.2.2.2.1.什么是PropertyValuesHolder
PropertyValuesHolder這個(gè)類的意義就是夺鲜,它其中保存了動(dòng)畫過程中所需要操作的屬性和對(duì)應(yīng)的值皆尔。
我們通過ofFloat(Object target, String propertyName, float… values)構(gòu)造的動(dòng)畫,ofFloat()的內(nèi)部實(shí)現(xiàn)其實(shí)就是將傳進(jìn)來的參數(shù)封裝成PropertyValuesHolder實(shí)例來保存動(dòng)畫狀態(tài)币励。在封裝成PropertyValuesHolder實(shí)例以后慷蠕,后期的各種操作也是以PropertyValuesHolder為主的。
ObjectAnimator給我們提供了一個(gè)口子食呻,讓我們自己構(gòu)造PropertyValuesHolder來構(gòu)造動(dòng)畫流炕。
4.2.2.2.2 PropertyValuesHolder構(gòu)造函數(shù)
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常用方法
//設(shè)置動(dòng)畫的Evaluator
public void setEvaluator(TypeEvaluator evaluator)
//用于設(shè)置ofFloat所對(duì)應(yīng)的動(dòng)畫值列表
public void setFloatValues(float... values)
//用于設(shè)置ofInt所對(duì)應(yīng)的動(dòng)畫值列表
public void setIntValues(int... values)
//用于設(shè)置ofKeyframe所對(duì)應(yīng)的動(dòng)畫值列表
public void setKeyframes(Keyframe... values)
//用于設(shè)置ofObject所對(duì)應(yīng)的動(dòng)畫值列表
public void setObjectValues(Object... values)
//設(shè)置動(dòng)畫屬性名
public void setPropertyName(String propertyName)
setFloatValues(float… values)對(duì)應(yīng)PropertyValuesHolder.ofFloat(),用于動(dòng)態(tài)設(shè)置動(dòng)畫中的數(shù)值仅胞。setIntValues每辟、setKeyframes、setObjectValues同理干旧;
setPropertyName用于設(shè)置PropertyValuesHolder所需要操作的動(dòng)畫屬性名;
4.2.2.2.3 使用PropertyValuesHolder創(chuàng)建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
如果要控制動(dòng)畫速率的變化渠欺,我們可以通過自定義插值器,也可以通過自定義Evaluator來實(shí)現(xiàn)椎眯。但有一定的難度挠将。為了解決方便的控制動(dòng)畫速率的問題,谷歌定義了一個(gè)KeyFrame的類编整,也就是關(guān)鍵幀舔稀。
就是類似動(dòng)畫中的關(guān)鍵幀:
比如我們要讓一個(gè)球在30秒時(shí)間內(nèi),從(0,0)點(diǎn)運(yùn)動(dòng)到(300掌测,200)點(diǎn)镶蹋,我們只需要定義兩個(gè)關(guān)鍵幀,在動(dòng)畫開始時(shí)定義一個(gè)赏半,把球的位置放在(0,0)點(diǎn)贺归;在30秒后,再定義一個(gè)關(guān)鍵幀断箫,把球的位置放在(300拂酣,200)點(diǎn)。在動(dòng)畫 開始時(shí)仲义,球初始在是(0婶熬,0)點(diǎn)剑勾,30秒時(shí)間內(nèi)就adobe flash就會(huì)自動(dòng)填充,把球平滑移動(dòng)到第二個(gè)關(guān)鍵幀的位置(300赵颅,200)點(diǎn)虽另;
一個(gè)關(guān)鍵幀必須包含兩個(gè)原素,第一時(shí)間點(diǎn)饺谬,第二位置捂刺。即這個(gè)關(guān)鍵幀是表示的是某個(gè)物體在哪個(gè)時(shí)間點(diǎn)應(yīng)該在哪個(gè)位置上。
② KeyFrame 構(gòu)造方法
// 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:表示當(dāng)前的顯示進(jìn)度募寨,即從加速器中g(shù)etInterpolation()函數(shù)的返回值族展;
- value:表示當(dāng)前應(yīng)該在的位置
Keyframe kf0 = Keyframe.ofFloat(0, 0);
Keyframe kf1 = Keyframe.ofFloat(0.1f, -20f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0);
比如Keyframe.ofFloat(0, 0)表示動(dòng)畫進(jìn)度為0時(shí),動(dòng)畫所在的數(shù)值位置為0拔鹰;Keyframe.ofFloat(0.25f, -20f)表示動(dòng)畫進(jìn)度為25%時(shí)仪缸,動(dòng)畫所在的數(shù)值位置為-20;Keyframe.ofFloat(1f,0)表示動(dòng)畫結(jié)束時(shí)列肢,動(dòng)畫所在的數(shù)值位置為0恰画;
public static Keyframe ofFloat(float fraction)
- 參數(shù)fraction,表示當(dāng)前關(guān)鍵幀所在的動(dòng)畫進(jìn)度位置瓷马。
那在這個(gè)進(jìn)度時(shí)所對(duì)應(yīng)的值 用setValue來設(shè)置
③KeyFrame常用方法
//設(shè)置fraction參數(shù)拴还,即Keyframe所對(duì)應(yīng)的進(jìn)度
public void setFraction(float fraction)
//設(shè)置當(dāng)前Keyframe所對(duì)應(yīng)的值
public void setValue(Object value)
//設(shè)置Keyframe動(dòng)作期間所對(duì)應(yīng)的插值器
public void setInterpolator(TimeInterpolator interpolator)
③ 代碼實(shí)現(xiàn)
1.使用ofFloat/ofInt構(gòu)造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構(gòu)造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();
④ 關(guān)于KeyFrame的插值器的注意點(diǎn)
關(guān)鍵幀可通過以下方法設(shè)置插值器
//設(shè)置Keyframe動(dòng)作期間所對(duì)應(yīng)的插值器
public void setInterpolator(TimeInterpolator interpolator)
如果給這個(gè)Keyframe設(shè)置上插值器,
那么這個(gè)插值器就是從上一個(gè)Keyframe開始到當(dāng)前設(shè)置插值器的Keyframe時(shí)决采,這個(gè)過程值的計(jì)算是利用這個(gè)插值器的
Keyframe frame0 = Keyframe.ofFloat(0f, 0);
Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
frame1.setInterpolator(new BounceInterpolator());
在frame0到frame1的中間值計(jì)算過程中,就是用的就是回彈插值坟奥。
給Keyframe.ofFloat(0f, 0)設(shè)置插值器是無效的树瞭,因?yàn)樗堑谝粠?/p>
⑤ 關(guān)于關(guān)鍵幀KeyFrame的注意點(diǎn)
如果去掉第0幀(fraction為0),將以第一個(gè)關(guān)鍵幀為起始位置
如果去掉結(jié)束幀(fraction為1)爱谁,將以最后一個(gè)關(guān)鍵幀為結(jié)束位置
使用Keyframe來構(gòu)建動(dòng)畫晒喷,至少要有兩個(gè)或兩個(gè)以上幀,否則會(huì)崩
4.2.3 ObjectAnimator動(dòng)畫原理
1??首先通過加速器產(chǎn)生當(dāng)前進(jìn)度的百分比访敌,
然后再經(jīng)過Evaluator生成對(duì)應(yīng)百分比所對(duì)應(yīng)的數(shù)字值凉敲。
這兩步與ValueAnimator是完全一樣的,
2??唯一不同的是最后一步
在ValueAnimator中寺旺,我們要通過添加監(jiān)聽器來監(jiān)聽當(dāng)前數(shù)字值爷抓。
而在ObjectAnimator中,則是先根據(jù)屬性值拼裝成對(duì)應(yīng)的set函數(shù)的名字阻塑,比如這里的scaleY的拼裝方法就是將屬性的第一個(gè)字母強(qiáng)制大寫后蓝撇,與set拼接,所以就是setScaleY陈莽。然后通過反射找到對(duì)應(yīng)控件的setScaleY(float scaleY)函數(shù)渤昌,將當(dāng)前數(shù)字值做為setScaleY(float scale)的參數(shù)將其傳入虽抄。
3??調(diào)用完set方法,set方法內(nèi)部會(huì)對(duì)控件進(jìn)行設(shè)置独柑,動(dòng)畫在進(jìn)行時(shí)每隔十幾毫秒會(huì)刷新一次迈窟,set函數(shù)也會(huì)每隔十幾毫秒會(huì)被調(diào)用一次(將動(dòng)畫中間值傳給他)。
4.2.4 ObjectAnimator XML實(shí)現(xiàn)
標(biāo)簽<objectAnimator />對(duì)應(yīng)ObjectAnimator
4.2.4.1 <objectAnimator />標(biāo)簽字段意義及使用方法
<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:對(duì)應(yīng)屬性名忌栅,即ObjectAnimator所需要操作的屬性名车酣。
android:valueType:表示參數(shù)值類型,取值為intType和floatType狂秘;與android:valueFrom骇径、android:valueTo相對(duì)應(yīng)。
4.2.4.2 代碼實(shí)現(xiàn)
- 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"
/>
- 加載動(dòng)畫
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.animator_object);
animator.setTarget(tvAnimPropertyObject);
animator.start();