一、 屬性動畫引入的背景
1、view動畫的不足之處
1、作用的對象隻能是view
2、隻能播放view的四種動畫或動畫組合(透明漸變、平移、縮放、旋轉)
3、非view對象不能使用view動畫
4、太局限 靈活性差
5、補間動畫還有一個緻命的缺陷,就是它隻是改變了View的顯示效果而已,而不會真正去改變View的屬性。(這點可以給按鈕設定點選事件進行平移動畫測試點選位置)
2、屬性動畫
屬性動畫機制已經不再是針對于View來設計的了。它實際上是一種不斷地對值進行操作的機制,并将值指派到指定對象的指定屬性上,可以是任意對象的任意屬性。我們隻需要告訴系統動畫的運作時長,需要執行哪種類型的動畫,以及動畫的初始值和結束值,剩下的工作就可以全部交給系統去完成了。
3、幾個常用的類
- Animator 屬性動畫基類
- ValueAnimator 值動畫
- ObjectAnimator 對象動畫
- AnimatorSet 屬性動畫集合
4、幾個類之間關系
(1)動畫基類Animator :

屬性動畫基類
(2)關系類圖
二、屬性動畫
1、ValueAnimator
(1)ValueAnimator簡介
由于Animator是抽象類,ValueAnimator 是直接繼承 Animator的。ValueAnimator還負責管理動畫的播放次數、播放模式、以及對動畫設定監聽器等(Animator的這些方法都在ValueAnimator 實作),确實是一個非常重要的類。是以ValueAnimator 是整個屬性動畫機制當中最核心的一個類。
(2)屬性動畫工作機制
屬性動畫的運作機制是通過不斷地對值進行操作來實作的,而初始值和結束值之間的動畫過渡就是由ValueAnimator這個類來負責計算的。它的内部使用一種時間循環的機制來計算值與值之間的動畫過渡,我們隻需要将初始值和結束值提供給ValueAnimator,并且告訴它動畫所需運作的時長,那麼ValueAnimator就會自動幫我們完成從初始值平滑地過渡到結束值這樣的效果。
(3)ValueAnimator 的使用
通過上文我們了解 屬性動畫可以作用于任何對象,其實也可以不作用對象而直接播放動畫(如下栗子)
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.setDuration(400);
valueAnimator.start();
// 這樣就開啟了一個簡單的動畫,表示吧一個值從0變化到1,執行時長300ms。
不作用與對象也可以播放動畫?哇真的很強大,可是不作用對象我們運作代碼怎沒看到?怎沒确定動畫播放了?我們可以設定動畫監聽啊!!!栗子如下:
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f);
valueAnimator.setDuration(400);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
Log.i("blabla", "onAnimationUpdate: " + value);
}
});
valueAnimator.start();
// log 如下,可以看到數值從0到1平滑的改變。
2019-06-11 10:38:15.289 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.0
2019-06-11 10:38:15.331 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.0
2019-06-11 10:38:15.505 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.36806342
2019-06-11 10:38:15.608 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.7477293
2019-06-11 10:38:15.642 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.8535534
2019-06-11 10:38:15.650 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.89507747
2019-06-11 10:38:15.703 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.9822787
2019-06-11 10:38:15.716 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 0.99554986
2019-06-11 10:38:15.730 25924-25924/com.example.myapplication I/blabla: onAnimationUpdate: 1.0
ofFloat方法:
* @param values A set of values that the animation will animate between over time.
* @return A ValueAnimator object that is set up to animate between the given values.
*/
public static ValueAnimator ofFloat(float... values) {
ValueAnimator anim = new ValueAnimator();
anim.setFloatValues(values);
return anim;
}
這個方法表示改變的值為float類型。參數為可變參數,代表值在這些參數内變化。如上我們設定0-1代表300ms内從0變化到1。假如我們設定0,1,3。數值将0變化到1再變化到3。
ofInt方法:
和ofFloat類似,隻是數值為int類型而不是小數類型。也是比較常用的方法
ofObject方法:
ObjectAnimator 中用的多,在ObjectAnimator 使用中再總結。
其他方法:
- setStartDelay 設定動畫延遲播放時間
- setRepeatCount 設定動畫循環次數
- setRepeatMode 設定動畫循環播放模式(RESTART:重新播放,REVERSE:倒序播放)
2、ObjectAnimator
(1)ValueAnimator 的特點
1、對值操作
2、值平滑的發生變化
3、平時使用場景不多
(2)ObjectAnimator特點
1、對對象的屬性進行操作
2、相比于ValueAnimator,ObjectAnimator可能才是我們最常接觸到的類
3、它其實是繼承自ValueAnimator的,底層的動畫實作機制也是基于ValueAnimator來完成的
方法ofFloat
* @param target The object whose property is to be animated. This object should
* @param propertyName The name of the property being animated.
* @param values A set of values that the animation will animate between over time.
* @return An ObjectAnimator object that is set up to animate between the given values.
*/
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
ObjectAnimator anim = new ObjectAnimator(target, propertyName);
anim.setFloatValues(values);
return anim;
}
和ValueAnimator 的ofFloat類似,有點小改動。
1、Object target 要操作的對象,對哪個對象進行動畫。
2、String propertyName 要操作對象的屬性,對哪個對象的屬性進行動畫。
3、 float… values 可變參數(值變化範圍,這點和ValueAnimator 的ofFloat的參數一樣)
簡單例子如下:
button = findViewById(R.id.btn);
// 參數1: object 對象
// 參數2: 操作的屬性 (屬性要有get set方法)
// 3-n : 可變參數 要執行動畫的數值變化範圍
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(button, "rotation", 0f, 360f);
objectAnimator.setDuration(5000);
objectAnimator.start();
動畫效果:按鈕旋轉360度
有了旋轉rotation,其實我們也可以設定屬性為:
- alpha(透明度變化)
- translationX(x軸方向平移)
- translationY(y軸方向平移)
- scaleY
- scaleX
- 等等
或許我們疑問:ObjectAnimator的ofFloat的第二個參數可以為那些屬性值?上面我們知道可以傳alpha、translationX、translationY、scaleY、scaleX等等。其實我們可以傳入任意的值到ofFloat()方法的第二個參數當中。但事實就是如此。因為ObjectAnimator在設計的時候就沒有針對于View來進行設計,而是針對于任意對象的,它所負責的工作就是不斷地向某個對象中的某個屬性進行指派,然後對象根據屬性值的改變再來決定如何展現出來。
(3)上述按鈕動畫栗子分析
1、其實這段代碼的意思就是ObjectAnimator會幫我們不斷地改變Button對象中rotation屬性的值,從0f變化到360f。然後button對象需要根據rotation屬性值的改變來不斷重新整理界面的顯示,進而讓使用者可以看出旋轉的動畫效果。
2、那麼button對象中是不是有rotation屬性這個值呢?沒有,不僅button沒有這個屬性,連它所有的父類也是沒有這個屬性的!這就奇怪了,button當中并沒有rotation這個屬性,ObjectAnimator是如何進行操作的呢?其實ObjectAnimator内部的工作機制并不是直接對我們傳入的屬性名進行操作的,而是會去尋找這個屬性名對應的get和set方法,是以rotation屬性所對應的get和set方法應該就是(如下代碼)
3、那麼button對象中是否有這兩個方法呢?确實有,并且這兩個方法是由View對象提供的,也就是說不僅button可以使用這個屬性來進行淡入淡出動畫操作,任何繼承自View的對象都可以的。
4、既然rotation 可以那麼我們上述說的alpha等等都可以了
ps:對象要有get set方法才能進行屬性動畫
public void setRotation(float value);
public float getRotation();
3、AnimatorSet-屬性動畫集合
(1)控制動畫播放順序的api
- after(Animator anim) 将現有動畫插入到傳入的動畫之後執行
- after(long delay) 将現有動畫延遲指定毫秒後執行
- before(Animator anim) 将現有動畫插入到傳入的動畫之前執行
- with(Animator anim) 将現有動畫和傳入的動畫同時執行
這幾個api的傳回值都是AnimatorSet.Builder類型執行個體,builder模式鍊式調用(如下play的源碼)
//AnimatorSet的方法
public Builder play(Animator anim) {
if (anim != null) {
return new Builder(anim);
}
return null;
}
(2)栗子
// 旋轉
ObjectAnimator rotation = ObjectAnimator.ofFloat(button, "rotation", 0f, 360f);
// 平移
float translationX = button.getTranslationX();
ObjectAnimator translation = ObjectAnimator.ofFloat(button, "translationX", translationX, -500f, translationX);
// 透明
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(button, "alpha", 1f, 0f, 1f);
// 動畫集合播放上述動畫
AnimatorSet animatorSet = new AnimatorSet();
// 先播放 translation 再同時播放rotation、fadeInOut
animatorSet.play(rotation).with(fadeInOut).after(translation);
animatorSet.setDuration(3000);
animatorSet.start();
(4)Animator監聽器
動畫怎沒能沒有監聽呢?是以Animator提供了監聽方法addListener(AnimatorListener listener),我們隻需要實作這個listener就行啦。。。。。由于這方法是Animator提供是以屬性動畫通用。
- AnimatorListener
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.i("blabla", "onAnimationStart: ");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.i("blabla", "onAnimationEnd: ");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.i("blabla", "onAnimationCancel: ");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.i("blabla", "onAnimationRepeat: ");
}
});
- AnimatorListenerAdapter
如上AnimatorListener使用時需要重寫四個方法但是有時候我們可能不需要重寫這麼多,有時我們可能隻需要重寫一個,這時Android提供了一個擴充卡類,叫作AnimatorListenerAdapter,使用這個類就可以解決掉實作接口繁瑣的問題了。(栗子如下)
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.addListener(new AnimatorListenerAdapter() {
// 重寫想使用的方法即可
@Override
public void onAnimationStart(Animator animation) {
// todo
}
});
三、屬性動畫的xml實作
我們可以使用代碼來編寫所有的動畫功能,這也是最常用的一種做法。不過,過去的補間動畫除了使用代碼編寫之外也是可以使用XML編寫的,是以屬性動畫也提供了這一功能,即通過XML來完成和代碼一樣的屬性動畫功能。
1、xml編寫的優缺點
優點:
代碼重用友善
缺點:
編寫相對java代碼麻煩
擴充性不高(比如動态獲得手機資訊就需要java代碼實作)
2、标簽
- animator 對應代碼中的ValueAnimator
- objectAnimator 對應代碼中的ObjectAnimator
- set 對應代碼中的AnimatorSet
3、編寫步驟
首先要在res目錄下面建立一個animator檔案夾![]()
Android動畫深入分析-屬性動畫初級用法一、 屬性動畫引入的背景二、屬性動畫三、屬性動畫的xml實作end
4、栗子
(1)從0到100平滑過渡的動畫
<animator android:duration="3000"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"/>
(2)将一個視圖的alpha屬性從1變成0
<objectAnimator
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:propertyName="alpha"/>
(3)組合動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<animator
android:duration="3000"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
<objectAnimator
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
android:propertyName="alpha"/>
</set>
5、 xml動畫資源加載
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.test);
animator.setTarget(button);
animator.start();
end
參考:
1、安卓開發藝術探索
2、https://blog.csdn.net/guolin_blog/article/details/43536355
屬性動畫中級用法