Property Animation屬性動畫

動畫類型

  • View Animation(Tween Animation 補間動畫)
    只能支持簡單的縮放、平移、旋轉、透明度等基本的動畫,且有一定的局限性
    動畫時View的真正的View的屬性保持不變,實際位置未改變
    原理:提供動畫的起始和結束狀態信息,中間的狀態根據上述類里差值器算法填充
  • Drawable Animation(Frame Animation 幀動畫)
  • Property Animation(屬性動畫)
    它更改的是對象的實際屬性,

Property Animation屬性

  • Duration:動畫的持續時間
  • TimeInterpolation:屬性值的計算方式,如先快后慢
  • TypeEvaluator:根據屬性的開始、結束值與TimeInterpolation計算出的因子計算出當前時間的屬性值
  • Repeat Count and behavoir:重復次數與方式,如播放3次、5次、無限循環,可以此動畫一直重復,或播放完時再反向播放
  • Animation sets:動畫集合,即可以同時對一個對象應用幾個動畫,這些動畫可以同時播放也可以對不同動畫設置不同開始偏移
  • Frame refreash delay:多少時間刷新一次,即每隔多少時間計算一次屬性值,默認為10ms,最終刷新時間還受系統進程調度與硬件的影響

Property Animation 動畫流程

ValueAnimator

ValueAnimator包含Property Animation動畫的所有核心功能,如動畫時間,開始、結束屬性值,相應時間屬性值計算方法等。應用Property Animation有兩個步聚:

  1. 計算屬性值
  2. 根據屬性值執行相應的動作,如改變對象的某一屬性。(需要在onAnimationUpdate中傳入執行動畫的對象)
/**
     * 自由落體
     * @param view
     */
        ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight
                - mBlueBall.getHeight());
        animator.setTarget(mBlueBall);
        animator.setDuration(1000).start();
//        animator.setInterpolator(new CycleInterpolator(3));
        animator.addUpdateListener(new AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
            // //這個函數中會傳入ValueAnimator對象做為參數,通過這個ValueAnimator對象的getAnimatedValue()函數可以得到當前的屬性值
                mBlueBall.setTranslationY((Float) animation.getAnimatedValue());
        
            }
        });
    }

    /**
     * 拋物線
     * @param view
     */
    public void paowuxian(View view)
    {

        ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setDuration(3000);
        valueAnimator.setObjectValues(new PointF(0, 0));
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setEvaluator(new TypeEvaluator<PointF>()
        {
            // fraction = t / duration
            @Override
            public PointF evaluate(float fraction, PointF startValue,
                    PointF endValue)
            {
                Log.e(TAG, fraction * 3 + "");
                // x方向200px/s ,則y方向0.5 * 10 * t
                PointF point = new PointF();
                point.x = 200 * fraction * 3;
                point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3);
                return point;
            }
        });

        valueAnimator.start();
        valueAnimator.addUpdateListener(new AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator animation)
            {
                PointF point = (PointF) animation.getAnimatedValue();
                mBlueBall.setX(point.x);
                mBlueBall.setY(point.y);

            }
        });
    }

ObjectAnimator

ObjectAnimator繼承自ValueAnimator,要指定一個對象及該對象的一個屬性,例如

  • 常用方法有ofFloat(),ofInt(),ofObject(),ofArgb(),ofPropertyValuesHolder()。
  • 屬性動畫可用的屬性
    答案是:任何一切帶有set開頭的方法屬性名字。可能我們常用的有:
  • 平移 translationX,translationY, X,Y。
  • 縮放 scaleX,scaleY。
  • 旋轉 rotationX, rotationY。
  • 透明度 alpha。

也就是說我們所有控件都有以上setTranslationX(),setScaleX(),setRotationX(),setAlpha()等方法。
我們不僅限于這幾個屬性,就拿TextView控件來說,只要是TextView有的屬性都可以用來實現動畫效果,比如 字體大小:“textColor”,字體顏色“textSize”等。

限制:對象應該有一個setter函數:set<PropertyName>(駝峰命名法)及要有相應屬性的getter方法:get<PropertyName>
且應返回值類型應與相應的setter方法的參數類型一致。
如果上述條件不滿足,則不能用ObjectAnimator,應用ValueAnimator代替。

 ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, 'alpha', 1.0f, 0.3f, 1.0F);
        animator.setDuration(2000);//動畫時間
        animator.setInterpolator(new BounceInterpolator());//動畫插值
        animator.setRepeatCount(-1);//設置動畫重復次數
        animator.setRepeatMode(ValueAnimator.RESTART);//動畫重復模式
        animator.setStartDelay(1000);//動畫延時執行
        animator.start();//啟動動畫
                        ```
> 根據應用動畫的對象或屬性的不同,如果內部沒有調用view的重繪,可能需要在onAnimationUpdate函數中調用invalidate()函數刷新視圖。

###組合動畫
 - **組合動畫1–AnimatorSet的使用**
這個類提供了一個play()方法,如果我們向這個方法中傳入一個Animator對象(ValueAnimator或ObjectAnimator)將會返回一個AnimatorSet.Builder的實例,AnimatorSet.Builder中包括以下四個方法:
   - after(Animator anim) 將現有動畫插入到傳入的動畫之后執行
   - after(long delay) 將現有動畫延遲指定毫秒后執行
   - before(Animator anim) 將現有動畫插入到傳入的動畫之前執行
   - with(Animator anim) 將現有動畫和傳入的動畫同時執行
   
   > Android 除了提供play(),還有playSequentially(),playTogether() 可供使用,可傳入一個或者多個動畫對象(,隔開),或者動畫集合
   

ObjectAnimator animator = ObjectAnimator.ofInt(container, "backgroundColor", 0xFFFF0000, 0xFFFF00FF);
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 0.0f, 200.0f, 0f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 2.0f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "rotationX", 0.0f, 90.0f, 0.0F);
ObjectAnimator animator4 = ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0.2f, 1.0F);

            //組合動畫方式1
            AnimatorSet set = new AnimatorSet();
           ((set.play(animator).with(animator1).before(animator2)).before(animator3)).after(animator4);
            set.setDuration(5000);
            set.start();
            ```
  • 組合動畫2–PropertyValuesHolder的使用
    使用方法ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder… values);第一個參數是動畫的目標對象,之后的參數是PropertyValuesHolder類的實例,可以有多個這樣的實例。代碼如下:
PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat("translationX", 0.0f, 300.0f);
                PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 1.5f);
                PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0f, 90.0f, 0.0F);
                PropertyValuesHolder valuesHolder3 = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.3f, 1.0F);

                ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(view, valuesHolder, valuesHolder1, valuesHolder2, valuesHolder3);
                objectAnimator.setDuration(2000).start();
                //類似于AnimatorSet.playTogether(Animator... items);
                ```
- **組合動畫3-ViewPropertyAnimator(多屬性動畫)**
    // need API12

ViewPropertyAnimator animator=mBlueBall.animate()
.alpha(0)
.y(mScreenHeight / 2).setDuration(1000)
// need API 12
.withStartAction(new Runnable()
{
@Override
public void run()
{
Log.e(TAG, "START");
}
// need API 16
}).withEndAction(new Runnable()
{
@Override
public void run()
{
Log.e(TAG, "END");
runOnUiThread(new Runnable()
{
@Override
public void run()
{
mBlueBall.setY(0);
mBlueBall.setAlpha(1.0f);
}
});
}
}).start();
}

> 注意:使用ViewPropertyAnimator類需要API>=12

### 動畫監聽
- animator.addListener(new Animator.AnimatorListener(){});//監聽動畫開始,結束,取消,重復(四種都包括)
- animator.addListener(new  AnimatorListenerAdapter(){});
推薦,可代替AnimatorListener,需要監聽動畫開始,結束,取消,重復那種就直接實現那種方法就行
其實AnimatorListenerAdapter的源碼只是一個實現了AnimatorListener接口的抽象類而已
- animator.addUpdateListener(new  ValueAnimator.AnimatorUpdateListener(){}); 
更加精確的方法來時刻監聽當前動畫的執行情況,可以讀取到動畫的每個更新值了

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
//可以根據自己的需要來獲取動畫更新值。
Log.e('TAG', 'the animation value is ' + value);
}
});


###Keyframes 
keyFrame是一個 時間/值 對,通過它可以定義一個在特定時間的特定狀態,即關鍵幀,而且在兩個keyFrame之間可以定義不同的Interpolator,就好像多個動畫的拼接,第一個動畫的結束點是第二個動畫的開始點。KeyFrame是抽象類,要通過ofInt(),ofFloat(),ofObject()獲得適當的KeyFrame,然后通過PropertyValuesHolder.ofKeyframe獲得PropertyValuesHolder對象,如以下例子:

/*

  • 動畫效果:btn對象的width屬性值使其:
  • 開始時 Width=400
  • 動畫開始1/4時 Width=200
  • 動畫開始1/2時 Width=400
  • 動畫開始3/4時 Width=100
  • 動畫結束時 Width=500
    */
    Keyframe kf0 = Keyframe.ofInt(0, 400);
    Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
    Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
    Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
    Keyframe kf3 = Keyframe.ofInt(1f, 500);
    PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
    ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);
    rotationAnim.setDuration(2000);
### Property Animation在XML中使用
- xml文件放在res/animator/中

<set xmlns:android='http://schemas.android.com/apk/res/android'
android:duration='2000'
android:ordering='sequentially'>

<objectAnimator
    android:propertyName='translationX'
    android:valueFrom='0'
    android:valueTo='200'
    android:valueType='floatType' />

<set android:ordering='together'>
    <objectAnimator
        android:propertyName='scaleX'
        android:valueFrom='1'
        android:valueTo='2'
        android:valueType='floatType' />
    <objectAnimator
        android:propertyName='rotationX'
        android:valueFrom='0'
        android:valueTo='90'
        android:valueType='floatType' /><!--動畫值的類型-->

</set>
- 通過AnimatorInflater.loadAnimator方法加載xml動畫返回一個Animator的對象,然后調用setTarget方法給動畫設置對象調用哪個start啟動動畫即可完成xml動畫效果

Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);
animator.setTarget(view);
animator.start();



###LayoutAnimation  布局動畫
- LayoutTransition為布局的容器設置動畫,當容器中的視圖層次發生變化時存在過渡的動畫效果。
- 過渡類型:
 - LayoutTransition.APPEARING 當一個View在ViewGroup中出現時,對**此View**設置的動畫
 - LayoutTransition.CHANGE_APPEARING 當一個View在ViewGroup中出現時,對此View對其他View位置造成影響,對**其他View**設置的動畫
 - LayoutTransition.DISAPPEARING  當一個View在ViewGroup中消失時,對**此View**設置的動畫
 - LayoutTransition.CHANGE_DISAPPEARING 當一個View在ViewGroup中消失時,對此View對其他View位置造成影響,對其**他View**設置的動畫
 - LayoutTransition.CHANGE 不是由于View出現或消失造成對其他View位置造成影響,然后對**其他View**設置的動畫。

- 步驟:
 1. 實例化一個LayoutTransition對象
 3. 使用setAnimator 設置LayoutTransition對象的動畫,這個動畫包含了上述四個類型。可以使用android自帶的動畫,也可以使用自定義動畫。本例中的自定義動畫效果和上例一樣。
  2. setLayoutTransition指定container的LayoutTransition對象
LayoutTransition transition = new LayoutTransition();
    transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
            transition.getAnimator(LayoutTransition.CHANGE_APPEARING));
    transition.setAnimator(LayoutTransition.APPEARING,
            null);
    transition.setAnimator(LayoutTransition.APPEARING, (mAppear
            .isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 1, 0): null));//可用使用自定義動畫
    transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,
            null);
    mGridLayout.setLayoutTransition(transition);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容