最後一點是SDK中提到的,不要在onCreate中調用start,因為AnimationDrawable還沒有完全跟Window相關聯,如果想要界面顯示時就開始動畫的話,可以在onWindowFoucsChanged()中調用start()。
3. Property Animation
屬性動畫,這個是在Android 3.0中才引進的,它更改的是對象的實際屬性,在View Animation(Tween Animation)中,其改變的是View的繪制效果,真正的View的屬性保持不變,比如無論你在對話中如何縮放Button的大小,Button的有效點選區域還是沒有應用動畫時的區域,其位置與大小都不變。而在Property Animation中,改變的是對象的實際屬性,如Button的縮放,Button的位置與大小屬性值都改變了。而且Property Animation不止可以應用于View,還可以應用于任何對象。Property
Animation隻是表示一個值在一段時間内的改變,當值改變時要做什麼事情完全是你自己決定的。
在Property Animation中,可以對動畫應用以下屬性:
Duration:動畫的持續時間
TimeInterpolation:屬性值的計算方式,如先快後慢
TypeEvaluator:根據屬性的開始、結束值與TimeInterpolation計算出的因子計算出目前時間的屬性值
Repeat Count and behavoir:重複次數與方式,如播放3次、5次、無限循環,可以此動畫一直重複,或播放完時再反向播放
Animation sets:動畫集合,即可以同時對一個對象應用幾個動畫,這些動畫可以同時播放也可以對不同動畫設定不同開始偏移
Frame refreash delay:多少時間重新整理一次,即每隔多少時間計算一次屬性值,預設為10ms,最終重新整理時間還受系統程序排程與硬體的影響
Interpolator
首先要了解為什麼需要插值器,因為在補間動畫中,我們一般隻定義關鍵幀(首幀或尾幀),然後由系統自動生成中間幀,生成中間幀的這個過程可以成為“插值”。插值器定義了動畫變化的速率,提供不同的函數定義變化值相對于時間的變化規則,可以定義各種各樣的非線性變化函數,比如加速、減速等。下面是幾種常見的插值器:
Interpolator對象
資源ID
功能作用
AccelerateDecelerateInterpolator
@android:anim/accelerate_decelerate_interpolator
先加速再減速
AccelerateInterpolator
@android:anim/accelerate_interpolator
加速
AnticipateInterpolator
@android:anim/anticipate_interpolator
先回退一小步然後加速前進
AnticipateOvershootInterpolator
@android:anim/anticipate_overshoot_interpolator
在上一個基礎上超出終點一小步再回到終點
BounceInterpolator
@android:anim/bounce_interpolator
最後階段彈球效果
CycleInterpolator
@android:anim/cycle_interpolator
周期運動
DecelerateInterpolator
@android:anim/decelerate_interpolator
減速
LinearInterpolator
@android:anim/linear_interpolator
勻速
OvershootInterpolator
@android:anim/overshoot_interpolator
快速到達終點并超出一小步最後回到終點
如果隻簡單地引用這些插值器還不能滿足需要的話,我們要考慮一下個性化插值器。我們可以建立一個插值器資源修改插值器的屬性,比如修改AnticipateInterpolator的加速速率,調整CycleInterpolator的循環次數等。為了完成這種需求,我們需要建立XML資源檔案,然後将其放于/res/anim下,然後再動畫元素中引用即可。我們先來看一下幾種常見的插值器可調整的屬性:
無
android:factor 浮點值,加速速率,預設為1
android:tension 浮點值,起始點後退的張力、拉力數,預設為2
android:tension 同上 android:extraTension 浮點值,拉力的倍數,預設為1.5(2 * 1.5)
無
android:cycles 整數值,循環的個數,預設為1
android:factor 浮點值,減速的速率,預設為1
無
浮點值,超出終點後的張力、拉力,預設為2
下面我們就拿最後一個插值器來舉例:
android:tension="7.0"/>
上面的代碼中,我們把張力改為7.0,然後将此檔案命名為my_overshoot_interpolator.xml,放置于/res/anim下,我們就可以引用到自定義的插值器了:
android:interpolator="@anim/my_overshoot_interpolator"
.../>
AccelerateDecelerateInterpolator
public class AccelerateDecelerateInterpolator implements Interpolator {
public AccelerateDecelerateInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}
}

AccelerateInterpolator
public class AccelerateInterpolator implements Interpolator {
private final float mFactor;
private final double mDoubleFactor;
public AccelerateInterpolator() {
mFactor = 1.0f;
mDoubleFactor = 2.0;
}
public AccelerateInterpolator(float factor) {
mFactor = factor;
mDoubleFactor = 2 * mFactor;
}
public AccelerateInterpolator(Context context, AttributeSet attrs) {
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator);
mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
mDoubleFactor = 2 * mFactor;
a.recycle();
}
public float getInterpolation(float input) {
if (mFactor == 1.0f) {
return input * input;
} else {
return (float)Math.pow(input, mDoubleFactor);
}
}
}
AnticipateInterpolator
public class AnticipateInterpolator implements Interpolator {
private final float mTension;
public AnticipateInterpolator() {
mTension = 2.0f;
}
public AnticipateInterpolator(float tension) {
mTension = tension;
}
public AnticipateInterpolator(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.AnticipateInterpolator);
mTension =
a.getFloat(com.android.internal.R.styleable.AnticipateInterpolator_tension, 2.0f);
a.recycle();
}
public float getInterpolation(float t) {
// a(t) = t * t * ((tension + 1) * t - tension)
return t * t * ((mTension + 1) * t - mTension);
}
}
AnticipateOvershootInterpolator
public class AnticipateOvershootInterpolator implements Interpolator {
private final float mTension;
public AnticipateOvershootInterpolator() {
mTension = 2.0f * 1.5f;
}
public AnticipateOvershootInterpolator(float tension) {
mTension = tension * 1.5f;
}
public AnticipateOvershootInterpolator(float tension, float extraTension) {
mTension = tension * extraTension;
}
public AnticipateOvershootInterpolator(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs, AnticipateOvershootInterpolator);
mTension = a.getFloat(AnticipateOvershootInterpolator_tension, 2.0f) *
a.getFloat(AnticipateOvershootInterpolator_extraTension, 1.5f);
a.recycle();
}
private static float a(float t, float s) {
return t * t * ((s + 1) * t - s);
}
private static float o(float t, float s) {
return t * t * ((s + 1) * t + s);
}
public float getInterpolation(float t) {
// a(t, s) = t * t * ((s + 1) * t - s)
// o(t, s) = t * t * ((s + 1) * t + s)
// f(t) = 0.5 * a(t * 2, tension * extraTension), when t < 0.5
// f(t) = 0.5 * (o(t * 2 - 2, tension * extraTension) + 2), when t <= 1.0
if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension);
else return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);
}
}
BounceInterpolator
public class BounceInterpolator implements Interpolator {
public BounceInterpolator() {
}
@SuppressWarnings({"UnusedDeclaration"})
public BounceInterpolator(Context context, AttributeSet attrs) {
}
private static float bounce(float t) {
return t * t * 8.0f;
}
public float getInterpolation(float t) {
// _b(t) = t * t * 8
// bs(t) = _b(t) for t < 0.3535
// bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408
// bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644
// bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0
// b(t) = bs(t * 1.1226)
t *= 1.1226f;
if (t < 0.3535f) return bounce(t);
else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;
else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;
else return bounce(t - 1.0435f) + 0.95f;
}
}
CycleInterpolator
public class CycleInterpolator implements Interpolator {
public CycleInterpolator(float cycles) {
mCycles = cycles;
}
public CycleInterpolator(Context context, AttributeSet attrs) {
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CycleInterpolator);
mCycles = a.getFloat(com.android.internal.R.styleable.CycleInterpolator_cycles, 1.0f);
a.recycle();
}
public float getInterpolation(float input) {
return (float)(Math.sin(2 * mCycles * Math.PI * input));
}
private float mCycles;
}
參數為2時的曲線:
DecelerateInterpolator
public class DecelerateInterpolator implements Interpolator {
public DecelerateInterpolator() {
}
public DecelerateInterpolator(float factor) {
mFactor = factor;
}
public DecelerateInterpolator(Context context, AttributeSet attrs) {
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.DecelerateInterpolator);
mFactor = a.getFloat(com.android.internal.R.styleable.DecelerateInterpolator_factor, 1.0f);
a.recycle();
}
public float getInterpolation(float input) {
float result;
if (mFactor == 1.0f) {
result = (float)(1.0f - (1.0f - input) * (1.0f - input));
} else {
result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));
}
return result;
}
private float mFactor = 1.0f;
}
LinearInterpolator
public class LinearInterpolator implements Interpolator {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
}
OvershootInterpolator
public class OvershootInterpolator implements Interpolator {
private final float mTension;
public OvershootInterpolator() {
mTension = 2.0f;
}
public OvershootInterpolator(float tension) {
mTension = tension;
}
public OvershootInterpolator(Context context, AttributeSet attrs) {
TypedArray a = context.obtainStyledAttributes(attrs,
com.android.internal.R.styleable.OvershootInterpolator);
mTension =
a.getFloat(com.android.internal.R.styleable.OvershootInterpolator_tension, 2.0f);
a.recycle();
}
public float getInterpolation(float t) {
// _o(t) = t * t * ((tension + 1) * t + tension)
// o(t) = _o(t - 1) + 1
t -= 1.0f;
return t * t * ((mTension + 1) * t + mTension) + 1.0f;
}
}