屬性動畫是 API 11 新加入的特性,和View動畫不同,它對作用對象進(jìn)行了擴(kuò)展,屬性動畫可以對任何對象做動畫而不僅僅是View,甚至還可以沒有對象。除了作用對象進(jìn)行了擴(kuò)展以外,屬性動畫的效果也得到了加強(qiáng)。
屬性動畫默認(rèn)時間間隔300ms,默認(rèn)幀率10ms/幀,其可達(dá)到的效果是:在一個時間間隔內(nèi)完成對象從一個屬性值到另一個屬性值的改變。因此,屬性動畫幾乎是無所不能的,只要對象有這個屬性,它都能實(shí)現(xiàn)動畫效果。但是屬性動畫從 API 11 才有,這就嚴(yán)重制約了屬性動畫的使用,可以采用開源動畫庫nineoldandroids來兼容以前的版本,nineoldandroids對屬性動畫做了兼容,在 API 11 以前的版本其內(nèi)部是通過代理View動畫來實(shí)現(xiàn)的,因此在Android低版本上,它的本質(zhì)還是View動畫,盡管使用方法看起來是屬性動畫。
屬性動畫有ValueAnimator、ObjectAnimator和AnimatorSet等概念。

本小節(jié)學(xué)習(xí)ValueAnimator。
一、概念
ValueAnimator,標(biāo)簽:<animator>
對屬性值進(jìn)行動畫,不會對UI造成改變,不能直接實(shí)現(xiàn)動畫效果,需要對動畫進(jìn)行監(jiān)聽,在監(jiān)聽過程中將這個屬性值設(shè)置給對應(yīng)的屬性,對應(yīng)的屬性才會改變。
二、實(shí)現(xiàn)
1. XML實(shí)現(xiàn)
//res/animator/value_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="5000"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"
/>
//布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/main_tv"
android:layout_width="wrap_content"
android:layout_height="100px"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="#FFFFFF"
android:text="Hello Android!"
android:background="@color/colorPrimary"/>
</RelativeLayout>
//代碼,MainActivity
private void valueAnimatorXML() {
mValueAnimator = (ValueAnimator)AnimatorInflater.loadAnimator(this, R.animator.value_animator);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
Log.d("MainActivity", "zwm, onAnimationUpdate value: " + value);
mMain_tv.setAlpha(value);
}
});
mValueAnimator.start();
}
private void stopAnimator() {
mValueAnimator.cancel();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
valueAnimatorXML();
}
@Override
protected void onDestroy() {
super.onDestroy();
stopAnimator();
}
2. 代碼實(shí)現(xiàn)
//布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/main_tv"
android:layout_width="wrap_content"
android:layout_height="100px"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="#FFFFFF"
android:text="Hello Android!"
android:background="@color/colorPrimary"/>
</RelativeLayout>
//代碼,MainActivity
private void valueAnimatorCode() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
mMain_tv.setAlpha(value);
}
});
valueAnimator.setDuration(5000);
valueAnimator.start();
}
private void stopAnimator() {
mValueAnimator.cancel();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
valueAnimatorCode();
}
@Override
protected void onDestroy() {
super.onDestroy();
stopAnimator();
}
在實(shí)際開發(fā)中建議采用代碼來實(shí)現(xiàn)屬性動畫,這是因為通過代碼來實(shí)現(xiàn)比較簡單。更重要的是,很多時候一個屬性的起始值是無法提前確定的,比如讓一個Button從屏幕左邊移動到屏幕右邊,由于我們無法提前知道屏幕的寬度,因此無法將屬性動畫定義在XML中,在這種情況下就必須通過代碼來動態(tài)地創(chuàng)建屬性動畫。
三、屬性
android:duration:
表示動畫的時長。
android:valueFrom:
表示屬性的起始值。
android:valueTo:
表示屬性的結(jié)束值。
android:startOffset:
表示動畫的延遲時間,當(dāng)動畫開始后,需要延遲多少毫秒才會真正播放此動畫。
android:repeatCount:
表示動畫的重復(fù)次數(shù)。默認(rèn)值為0,其中-1表示無限循環(huán)。
android:repeatMode:
表示動畫的重復(fù)模式。有"restart"和"reverse"兩個選項,分別表示連續(xù)重復(fù)和逆向重復(fù),連續(xù)重復(fù)就是每次都重新開始播放,逆向重復(fù)就是第一次播放完以后,第二次會倒著播放,第三次再重頭開始播放,第四次再倒著播放,如此重復(fù)。
android:valueType:
表示屬性的類型。有"intType"和"floatType"兩個選項,分別表示屬性的類型為整型和浮點(diǎn)型。
四、動畫過程監(jiān)聽
屬性動畫提供了監(jiān)聽器用于監(jiān)聽動畫的播放過程,主要有兩個接口:AnimatorUpdateListener和AnimatorListener。
AnimatorListener定義如下,它可以監(jiān)聽動畫的開始、結(jié)束、取消以及重復(fù)播放。
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}
AnimatorUpdateListener定義如下,它會監(jiān)聽整個動畫過程,動畫是由許多幀組成的,每播放一幀,onAnimationUpdate就會被調(diào)用一次。
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
實(shí)現(xiàn)如下:
private void valueAnimatorCode() {
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.d("MainActivity", "zwm, onAnimationStart");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.d("MainActivity", "zwm, onAnimationEnd");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.d("MainActivity", "zwm, onAnimationCancel");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.d("MainActivity", "zwm, onAnimationRepeat");
}
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) animation.getAnimatedValue();
Log.d("MainActivity", "zwm, onAnimationUpdate value: " + value);
mMain_tv.setAlpha(value);
}
});
valueAnimator.setDuration(5000);
valueAnimator.start();
}