補間動畫詳解四 平移動畫TranslateAnimation

TranslateAnimation是平移動畫的類,負責View的位移。

TranslateAnimation類官方文檔:
https://developer.android.com/reference/android/view/animation/TranslateAnimation.html

關於父類Animation的詳解可參考文章:
http://blog.csdn.net/ruancoder/article/details/52347243

一、TranslateAnimation的使用
(1).使用xml文件創建TranslateAnimation
屬性說明:
android:fromXDelta:動畫開始點的X軸座標。有三種表示方式,一是純數字,使用絕對位置(比如"50",表示以當前View左上角座標加50px作爲X座標);二是百分數,相對於控件本身定位(比如"50%",表示以當前View的左上角加上當前View寬度的50%作爲X座標);三是百分數p,相對於父控件定位(比如"50%p",表示以當前View的左上角加上父控件寬度的50%做爲X座標)。
android:fromYDelta:動畫開始點的Y軸座標。
android:toXDelta:動畫結束點的X軸座標。
android:toYDelta:動畫結束點的Y軸座標。

示例代碼:

從屏幕底部進入的動畫。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="3000">
    <translate
        android:fromYDelta="100%p"
        android:toYDelta="0.0"/>
</set>


從屏幕左側退出的動畫。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="3000">
    <translate
        android:fromXDelta="0.0"
        android:toXDelta="-100%p"/>
</set>

(2).使用java代碼創建TranslateAnimation
示例代碼:
//從當前位置,向下和向右各平移300px
TranslateAnimation animation = new TranslateAnimation(0.0f, 300.0f, 0.0f, 300.0f);
animation.setDuration(3000);
view.startAnimation(animation);

// 從屏幕底部進入的動畫
TranslateAnimation animation = new TranslateAnimation(
        Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f,
        Animation.RELATIVE_TO_PARENT, 1.0f, Animation.RELATIVE_TO_PARENT, 0.0f
);
animation.setDuration(3000);
view.startAnimation(animation);

二、TranslateAnimation的分析
TranslateAnimation繼承自Animation,除了擁有父類的屬性外,添加了mFromXType、mToXType、mFromYType、mToYType和mFromXValue、mToXValue、mFromYValue、mToYValue八個屬性。這個八個屬性可以通過構造方法或xml屬性傳入,最終由mFromXDelta、mToXDelta、mFromYDelta和mToYDelta參與動畫的計算。
public class TranslateAnimation extends Animation {
    private int mFromXType = ABSOLUTE;
    private int mToXType = ABSOLUTE;
    private int mFromYType = ABSOLUTE;
    private int mToYType = ABSOLUTE;


    protected float mFromXValue = 0.0f;
    protected float mToXValue = 0.0f;
    protected float mFromYValue = 0.0f;
    protected float mToYValue = 0.0f;


    protected float mFromXDelta;
    protected float mToXDelta;
    protected float mFromYDelta;
    protected float mToYDelta;
}

使用java代碼的方式創建TranslateAnimation,傳入六個參數,fromXType、fromXValue、toXType、toXValue和fromYType、fromYValue、toYType、toYValue,使用如下構造方法。
參數說明:
fromXType:動畫開始前的X座標類型。取值範圍爲ABSOLUTE(絕對位置)、RELATIVE_TO_SELF(以自身寬或高爲參考)、RELATIVE_TO_PARENT(以父控件寬或高爲參考)。
fromXValue:動畫開始前的X座標值。當對應的Type爲ABSOLUTE時,表示絕對位置;否則表示相對位置,1.0表示100%。
toXType:動畫結束後的X座標類型。
toXValue:動畫結束後的X座標值。
fromYType:動畫開始前的Y座標類型。
fromYValue:動畫開始前的Y座標值。
toYType:動畫結束後的Y座標類型。
toYValue:動畫結束後的Y座標值。
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
                          int fromYType, float fromYValue, int toYType, float toYValue) {


    mFromXValue = fromXValue;
    mToXValue = toXValue;
    mFromYValue = fromYValue;
    mToYValue = toYValue;


    mFromXType = fromXType;
    mToXType = toXType;
    mFromYType = fromYType;
    mToYType = toYType;
}

使用java代碼的方式創建TranslateAnimation,傳入四個參數,fromXDelta、toXDelta、fromYDelta和toYDelta,使用如下構造方法。
此時mFromXType、mToXType、mFromYType和mToYType默認爲ABSOLUTE。
參數說明:
fromXDelta:動畫開始前,離當前View X座標上的距離。
toXDelta:動畫結束後,離當前View X座標上的距離。
fromYDelta:動畫開始前,離當前View Y座標上的距離。
toYDelta:動畫結束後,離當前View Y座標上的距離。
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
    mFromXValue = fromXDelta;
    mToXValue = toXDelta;
    mFromYValue = fromYDelta;
    mToYValue = toYDelta;


    mFromXType = ABSOLUTE;
    mToXType = ABSOLUTE;
    mFromYType = ABSOLUTE;
    mToYType = ABSOLUTE;
}

當使用xml文件的方式創建TranslateAnimation時,由AnimationUtils工具類加載動畫文件,使用如下構造方法,通過xml中的屬性來獲取值。
public TranslateAnimation(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray a = context.obtainStyledAttributes(attrs,
            com.android.internal.R.styleable.TranslateAnimation);

    Animation.Description d = Animation.Description.parseValue(a.peekValue(
            com.android.internal.R.styleable.TranslateAnimation_fromXDelta));
    mFromXType = d.type;
    mFromXValue = d.value;

    d = Animation.Description.parseValue(a.peekValue(
            com.android.internal.R.styleable.TranslateAnimation_toXDelta));
    mToXType = d.type;
    mToXValue = d.value;

    d = Animation.Description.parseValue(a.peekValue(
            com.android.internal.R.styleable.TranslateAnimation_fromYDelta));
    mFromYType = d.type;
    mFromYValue = d.value;

    d = Animation.Description.parseValue(a.peekValue(
            com.android.internal.R.styleable.TranslateAnimation_toYDelta));
    mToYType = d.type;
    mToYValue = d.value;

    a.recycle();
}

完成成員變量的初始化後,接下來進入動畫的計算。核心在於重寫父類Animation的initialize()和applyTransformation()方法。

initialize()方法中,根據上面傳入的八個屬性值,結合當前View和父View的寬高,計算出平移的絕對位置。
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
    super.initialize(width, height, parentWidth, parentHeight);
    mFromXDelta = resolveSize(mFromXType, mFromXValue, width, parentWidth);
    mToXDelta = resolveSize(mToXType, mToXValue, width, parentWidth);
    mFromYDelta = resolveSize(mFromYType, mFromYValue, height, parentHeight);
    mToYDelta = resolveSize(mToYType, mToYValue, height, parentHeight);
}

protected float resolveSize(int type, float value, int size, int parentSize) {
    switch (type) {
        case ABSOLUTE:
            return value;
        case RELATIVE_TO_SELF:
            return size * value;
        case RELATIVE_TO_PARENT:
            return parentSize * value;
        default:
            return value;
    }
}

applyTransformation()方法負責動畫的執行。在動畫從開始倒結束的過程中,參數interpolatedTime從0.0遞增到1.0。通過不斷的調整dx和dy的值,調用Matrix的setTranslate()方法,達到平移View的效果。
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    float dx = mFromXDelta;
    float dy = mFromYDelta;
    if (mFromXDelta != mToXDelta) {
        dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
    }
    if (mFromYDelta != mToYDelta) {
        dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
    }
    t.getMatrix().setTranslate(dx, dy);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章