——轉(zhuǎn)自 黑馬論壇 唐楊老師
屬性動畫(Property Animation)系統(tǒng)是一個健壯的動畫框架系統(tǒng)铺峭,它可以滿足你大部分動畫需求墓怀。不管動畫對象是否已經(jīng)繪制到屏幕上,你都可以在動畫執(zhí)行過程中改變它任意的屬性值卫键。一個屬性動畫會在一段特定長度的時間內(nèi)改變一個屬性(一個對象中的字段)的值傀履。你可以通過以下幾步定義一個動畫:指定你要執(zhí)行動畫的屬性,比如動畫對象(View)在屏幕上的位置莉炉,指定執(zhí)行時長钓账,指定你希望的屬性的變化值碴犬。
同類技術(shù)對比:
1. 補(bǔ)間動畫(Tween Animation)
- 漸變動畫支持四種類型:平移(Translate)、旋轉(zhuǎn)(Rotate)官扣、縮放(Scale)翅敌、不透明度(Alpha)。
- 只是顯示的位置變動惕蹄,View的實(shí)際位置未改變蚯涮,表現(xiàn)為View移動到其他地方,點(diǎn)擊事件仍在原處才能響應(yīng)卖陵。
- 組合使用步驟較復(fù)雜遭顶。
- View Animation 也是指此動畫。
2. 幀動畫(Frame Animation)
- 用于生成連續(xù)的Gif效果圖泪蔫。
- Drawable Animation也是指此動畫棒旗。
3. 屬性動畫(Property Animation)
- 支持對所有View能更新的屬性的動畫(需要屬性的setXxx()和getXxx())。
- 更改的是View實(shí)際的屬性撩荣,所以不會影響其在動畫執(zhí)行后所在位置的正常使用铣揉。
- Android3.0 (API11)及以后出現(xiàn)的功能,3.0之前的版本可使用github第三方開源庫nineoldandroids.jar進(jìn)行支持餐曹。
屬性動畫組成部分逛拱、相關(guān)類介紹:
- ObjectAnimator :對象動畫執(zhí)行類。
- ValueAnimator :值動畫執(zhí)行類台猴,常配合AnimatorUpdateListener使用朽合。
- PropertyValuesHolder : 屬性存儲器,為兩個執(zhí)行類提供更新多個屬性的功能饱狂。
- Keyframe :為 PropertyValuesHolder提供多個關(guān)鍵幀的操作值曹步。
- AnimatorSet :一組動畫的執(zhí)行集合類:設(shè)置執(zhí)行的先后順序,時間等休讳。
- AnimatorUpdateListener :動畫更新監(jiān)聽讲婚。
- AnimatorListener :動畫執(zhí)行監(jiān)聽,在動畫開始俊柔、重復(fù)磺樱、結(jié)束、取消時進(jìn)行回調(diào)婆咸。
- AnimatorInflater :加載屬性動畫的xml文件竹捉。
- TypeEvaluator :類型估值,用于設(shè)置復(fù)雜的動畫操作屬性的值尚骄。
- TimeInterpolator :時間插值块差,用于控制動畫執(zhí)行過程。
一、ObjectAnimator 對象動畫執(zhí)行類
介紹:
- 通過靜態(tài)方法 ofInt憨闰、ofFloat状蜗、ofObject、ofPropertyValuesHolder 獲取類對象鹉动。
- 根據(jù)屬性值類型選擇靜態(tài)方法轧坎,如 view 的 setLeft(int left) 則選用 ofInt 方法, setY(float y) 則選用 ofFloat 方法。
- 同 ValueAnimator 一樣泽示,可以進(jìn)行串聯(lián)式使用缸血。
- 只能用于有 setXXX( )和 getXXX() 方法的屬性名稱!不然不會起作用械筛。
示例:
- 簡單示例:View 的橫向移動:
// 通過靜態(tài)方法構(gòu)建一個ObjectAnimator對象
// 設(shè)置作用對象捎泻、屬性名稱、數(shù)值集合
ObjectAnimator.ofFloat(view, "translationX", 0.0F, 200.0F)
// 設(shè)置執(zhí)行時間(1000ms)
.setDuration(1000)
// 開始動畫
.start();
- 復(fù)合示例:View 彈性落下然后彈起埋哟,執(zhí)行一次:
// 修改view的y屬性, 從當(dāng)前位置移動到300.0f
ObjectAnimator yBouncer = ObjectAnimator.ofFloat(view, "y",
view.getY(), 300.0f);
yBouncer.setDuration(1500);
// 設(shè)置插值器(用于調(diào)節(jié)動畫執(zhí)行過程的速度)
yBouncer.setInterpolator(new BounceInterpolator());
// 設(shè)置重復(fù)次數(shù)(缺省為0,表示不重復(fù)執(zhí)行)
yBouncer.setRepeatCount(1);
// 設(shè)置重復(fù)模式(RESTART或REVERSE),重復(fù)次數(shù)大于0或INFINITE生效
yBouncer.setRepeatMode(ValueAnimator.REVERSE);
// 設(shè)置動畫開始的延時時間(200ms)
yBouncer.setStartDelay(200);
// 開始動畫
yBouncer.start();
二笆豁、ValueAnimator 值動畫執(zhí)行類
介紹:
- 構(gòu)造方法與 ObjectAnimator 類似。
- 與 ObjectAnimator 的區(qū)別在于 ValueAnimator 構(gòu)造函數(shù)的參數(shù)中不包含動畫“屬性”信息赤赊。
- 優(yōu)點(diǎn):結(jié)合動畫更新監(jiān)聽** onAnimationUpdate() **使用闯狱,可以在回調(diào)中不斷更新 View 的多個屬性,使用起來更加靈活抛计。
示例:
View 向右下角移動:
// 通過靜態(tài)方法構(gòu)建一個ValueAnimator對象
// 設(shè)置數(shù)值集合
ValueAnimator animator = ValueAnimator.ofFloat(0f, 200.0f);
// 設(shè)置作用對象
animator.setTarget(view);
// 設(shè)置執(zhí)行時間(1000ms)
animator.setDuration(1000);
// 添加動畫更新監(jiān)聽
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 獲取當(dāng)前值
Float mValue = (Float) animation.getAnimatedValue();
// 設(shè)置橫向偏移量
view.setTranslationX(mValue);
// 設(shè)置縱向偏移量
view.setTranslationY(mValue);
}
});
// 開始動畫
animator.start();
-
可以理解為上面設(shè)置的 (0f, 200.0f)哄孤,0 到 200 的過程中,每次更新都會回調(diào) onAnimationUpdate()爷辱,每次回調(diào)都根據(jù)當(dāng)前值做一次動畫。
三朦肘、PropertyValuesHolder 屬性存儲器
介紹:
為 ValueAnimator 提供多個操作屬性及相應(yīng)的執(zhí)行參數(shù)饭弓。
示例:
同時修改 View 多個屬性的動畫:
// 獲取view左邊位置
int left = view.getLeft();
// 獲取view右邊位置
int right = view.getRight();
// 將view左邊增加10像素
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", left,
left + 10);
// 將view右邊減少10像素
PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right",
right, right - 10);
// 在X軸縮放從原始比例1f,縮小到最小0f,再放大到原始比例1f
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",
1f, 0f, 1f);
// 在Y軸縮放從原始比例1f,縮小到最小0f,再放大到原始比例1f
PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY",
1f, 0f, 1f);
// 將PropertyValuesHolder交付給ObjectAnimator進(jìn)行構(gòu)建
ObjectAnimator customAnim = ObjectAnimator.ofPropertyValuesHolder(view,
pvhLeft, pvhRight, pvhScaleX, pvhScaleY);
// 設(shè)置執(zhí)行時間(1000ms)
customAnim.setDuration(1000);
// 開始動畫
customAnim.start();
四、Keyframe 關(guān)鍵幀
介紹:
為 PropertyValuesHolder 提供關(guān)鍵幀的操作值集合媒抠。
示例:
以下示例表示該 PropertyValuesHolder 進(jìn)行的旋轉(zhuǎn)(rotation)動畫弟断,在執(zhí)行時間在 0%, 50%, 100% 時,其旋轉(zhuǎn)角度分別為 0°, 360°, 0°。動畫執(zhí)行過程中自動進(jìn)行補(bǔ)間趴生。表現(xiàn)為自旋 360° 后再轉(zhuǎn)回來:
// 設(shè)置在動畫開始時,旋轉(zhuǎn)角度為0度
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
// 設(shè)置在動畫執(zhí)行50%時,旋轉(zhuǎn)角度為360度
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
// 設(shè)置在動畫結(jié)束時,旋轉(zhuǎn)角度為0度
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
// 使用PropertyValuesHolder進(jìn)行屬性名稱和值集合的封裝
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe(
"rotation", kf0, kf1, kf2);
// 通過ObjectAnimator進(jìn)行執(zhí)行
ObjectAnimator.ofPropertyValuesHolder(view, pvhRotation)
// 設(shè)置執(zhí)行時間(1000ms)
.setDuration(1000)
// 開始動畫
.start();
五阀趴、AnimatorSet 執(zhí)行集合類
介紹:
- 為多個屬性動畫提供播放順序控制(注意 **play,with,after,before **的用法)。
- AnimatorSet 類與 AnimationSet 類不能搞混苍匆,AnimatorSet 在 3.0 及以上版本中才有刘急。3.0 之前的版本可使用第三方開源庫 nineoldandroids.jar 進(jìn)行支持,功能使用完全一致浸踩。
示例:
以下示例動畫的播放順序?yàn)?/p>
- 播放 bounceAnim;
- 同時播放 squashAnim1, squashAnim2,stretchAnim1, stretchAnim2;
- 接著播放 bounceBackAnim;
- 最后播放 fadeAnim;
AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f,
0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();
六叔汁、AnimatorListener 動畫執(zhí)行監(jiān)聽
介紹:
- 實(shí)現(xiàn) AnimatorListener 中的方法可在動畫執(zhí)行全程進(jìn)行其他任務(wù)的回調(diào)執(zhí)行。
- 也可以添加 AnimatorListener 的實(shí)現(xiàn)類 AnimatorListenerAdapter,僅重寫需要的監(jiān)聽即可据块。
示例:
將 view 透明度從當(dāng)前的 1.0f 更新為0.5f码邻,在動畫結(jié)束時移除該 View:
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
anim.setDuration(1000);
anim.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// 動畫開始時調(diào)用
}
@Override
public void onAnimationRepeat(Animator animation) {
// 動畫重復(fù)時調(diào)用
}
@Override
public void onAnimationEnd(Animator animation) {
// 動畫結(jié)束時調(diào)用
ViewGroup parent = (ViewGroup) view.getParent();
if (parent != null)
parent.removeView(view);
}
@Override
public void onAnimationCancel(Animator animation) {
// 動畫取消時調(diào)用
}
});
anim.start();
七、AnimatorInflater 動畫加載器
介紹:
- 屬性動畫可以通過 xml 文件的形式加載另假。
- set 標(biāo)簽內(nèi)的 animator 也可單獨(dú)使用像屋。
- XML語法如下:
<set android:ordering=["together" | "sequentially"]>
<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"]/>
<animator
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"]/>
<set>
...
</set>
</set>
示例:
<?xml version="1.0" encoding="utf-8"?>
<set>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="200"
android:valueType="floatType"
android:propertyName="x"
android:repeatCount="1"
android:repeatMode="reverse"/>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueTo="400"
android:valueType="floatType"
android:propertyName="y"
android:repeatCount="1"
android:repeatMode="reverse"/>
</set>
// 加載xml屬性動畫
Animator anim = AnimatorInflater
.loadAnimator(this, R.anim.animator_set);
anim.setTarget(view);
anim.start();
八、TypeEvaluator 類型估值
介紹:
- TypeEvaluator 可傳入?yún)?shù)值的類型(本例為 PointF)边篮。
- 重寫函數(shù) public T evaluate(floatfraction, T startValue, T endValue);實(shí)現(xiàn)不同需求值的計(jì)算己莺。
- 注意 fraction 的使用,fraction 是從開始到結(jié)束的分度值 0.0 -> 1.0苟耻。