Property Animation屬性動(dòng)畫(huà)

動(dòng)畫(huà)類型

  • View Animation(Tween Animation 補(bǔ)間動(dòng)畫(huà))
    只能支持簡(jiǎn)單的縮放样傍、平移捂贿、旋轉(zhuǎn)渤弛、透明度等基本的動(dòng)畫(huà)泛释,且有一定的局限性
    動(dòng)畫(huà)時(shí)View的真正的View的屬性保持不變滤愕,實(shí)際位置未改變
    原理:提供動(dòng)畫(huà)的起始和結(jié)束狀態(tài)信息,中間的狀態(tài)根據(jù)上述類里差值器算法填充
  • Drawable Animation(Frame Animation 幀動(dòng)畫(huà))
  • Property Animation(屬性動(dòng)畫(huà))
    它更改的是對(duì)象的實(shí)際屬性怜校,

Property Animation屬性

  • Duration:動(dòng)畫(huà)的持續(xù)時(shí)間
  • TimeInterpolation:屬性值的計(jì)算方式间影,如先快后慢
  • TypeEvaluator:根據(jù)屬性的開(kāi)始、結(jié)束值與TimeInterpolation計(jì)算出的因子計(jì)算出當(dāng)前時(shí)間的屬性值
  • Repeat Count and behavoir:重復(fù)次數(shù)與方式茄茁,如播放3次魂贬、5次、無(wú)限循環(huán)胰丁,可以此動(dòng)畫(huà)一直重復(fù)随橘,或播放完時(shí)再反向播放
  • Animation sets:動(dòng)畫(huà)集合,即可以同時(shí)對(duì)一個(gè)對(duì)象應(yīng)用幾個(gè)動(dòng)畫(huà)锦庸,這些動(dòng)畫(huà)可以同時(shí)播放也可以對(duì)不同動(dòng)畫(huà)設(shè)置不同開(kāi)始偏移
  • Frame refreash delay:多少時(shí)間刷新一次机蔗,即每隔多少時(shí)間計(jì)算一次屬性值,默認(rèn)為10ms甘萧,最終刷新時(shí)間還受系統(tǒng)進(jìn)程調(diào)度與硬件的影響

Property Animation 動(dòng)畫(huà)流程

ValueAnimator

ValueAnimator包含Property Animation動(dòng)畫(huà)的所有核心功能萝嘁,如動(dòng)畫(huà)時(shí)間,開(kāi)始扬卷、結(jié)束屬性值牙言,相應(yīng)時(shí)間屬性值計(jì)算方法等。應(yīng)用Property Animation有兩個(gè)步聚:

  1. 計(jì)算屬性值
  2. 根據(jù)屬性值執(zhí)行相應(yīng)的動(dòng)作怪得,如改變對(duì)象的某一屬性咱枉。(需要在onAnimationUpdate中傳入執(zhí)行動(dòng)畫(huà)的對(duì)象)
/**
     * 自由落體
     * @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)
            {
            // //這個(gè)函數(shù)中會(huì)傳入ValueAnimator對(duì)象做為參數(shù),通過(guò)這個(gè)ValueAnimator對(duì)象的getAnimatedValue()函數(shù)可以得到當(dāng)前的屬性值
                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蚕断,要指定一個(gè)對(duì)象及該對(duì)象的一個(gè)屬性,例如

  • 常用方法有ofFloat(),ofInt()入挣,ofObject()亿乳,ofArgb(),ofPropertyValuesHolder()径筏。
  • 屬性動(dòng)畫(huà)可用的屬性
    答案是:任何一切帶有set開(kāi)頭的方法屬性名字葛假。可能我們常用的有:
  • 平移 translationX滋恬,translationY, X聊训,Y。
  • 縮放 scaleX夷恍,scaleY魔眨。
  • 旋轉(zhuǎn) rotationX媳维, rotationY。
  • 透明度 alpha遏暴。

也就是說(shuō)我們所有控件都有以上setTranslationX(),setScaleX(),setRotationX(),setAlpha()等方法侄刽。
我們不僅限于這幾個(gè)屬性,就拿TextView控件來(lái)說(shuō)朋凉,只要是TextView有的屬性都可以用來(lái)實(shí)現(xiàn)動(dòng)畫(huà)效果州丹,比如 字體大小:“textColor”杂彭,字體顏色“textSize”等墓毒。

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

 ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, 'alpha', 1.0f, 0.3f, 1.0F);
        animator.setDuration(2000);//動(dòng)畫(huà)時(shí)間
        animator.setInterpolator(new BounceInterpolator());//動(dòng)畫(huà)插值
        animator.setRepeatCount(-1);//設(shè)置動(dòng)畫(huà)重復(fù)次數(shù)
        animator.setRepeatMode(ValueAnimator.RESTART);//動(dòng)畫(huà)重復(fù)模式
        animator.setStartDelay(1000);//動(dòng)畫(huà)延時(shí)執(zhí)行
        animator.start();//啟動(dòng)動(dòng)畫(huà)
                        ```
> 根據(jù)應(yīng)用動(dòng)畫(huà)的對(duì)象或?qū)傩缘牟煌呕啵绻麅?nèi)部沒(méi)有調(diào)用view的重繪主胧,可能需要在onAnimationUpdate函數(shù)中調(diào)用invalidate()函數(shù)刷新視圖。

###組合動(dòng)畫(huà)
 - **組合動(dòng)畫(huà)1–AnimatorSet的使用**
這個(gè)類提供了一個(gè)play()方法习勤,如果我們向這個(gè)方法中傳入一個(gè)Animator對(duì)象(ValueAnimator或ObjectAnimator)將會(huì)返回一個(gè)AnimatorSet.Builder的實(shí)例踪栋,AnimatorSet.Builder中包括以下四個(gè)方法:
   - after(Animator anim) 將現(xiàn)有動(dòng)畫(huà)插入到傳入的動(dòng)畫(huà)之后執(zhí)行
   - after(long delay) 將現(xiàn)有動(dòng)畫(huà)延遲指定毫秒后執(zhí)行
   - before(Animator anim) 將現(xiàn)有動(dòng)畫(huà)插入到傳入的動(dòng)畫(huà)之前執(zhí)行
   - with(Animator anim) 將現(xiàn)有動(dòng)畫(huà)和傳入的動(dòng)畫(huà)同時(shí)執(zhí)行
   
   > Android 除了提供play(),還有playSequentially(),playTogether() 可供使用,可傳入一個(gè)或者多個(gè)動(dòng)畫(huà)對(duì)象(图毕,隔開(kāi))夷都,或者動(dòng)畫(huà)集合
   

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);

            //組合動(dòng)畫(huà)方式1
            AnimatorSet set = new AnimatorSet();
           ((set.play(animator).with(animator1).before(animator2)).before(animator3)).after(animator4);
            set.setDuration(5000);
            set.start();
            ```
  • 組合動(dòng)畫(huà)2–PropertyValuesHolder的使用
    使用方法ObjectAnimator.ofPropertyValuesHolder(Object target,PropertyValuesHolder… values);第一個(gè)參數(shù)是動(dòng)畫(huà)的目標(biāo)對(duì)象予颤,之后的參數(shù)是PropertyValuesHolder類的實(shí)例囤官,可以有多個(gè)這樣的實(shí)例。代碼如下:
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);
                ```
- **組合動(dòng)畫(huà)3-ViewPropertyAnimator(多屬性動(dòng)畫(huà))**
    // 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

### 動(dòng)畫(huà)監(jiān)聽(tīng)
- animator.addListener(new Animator.AnimatorListener(){});//監(jiān)聽(tīng)動(dòng)畫(huà)開(kāi)始蛤虐,結(jié)束治拿,取消,重復(fù)(四種都包括)
- animator.addListener(new  AnimatorListenerAdapter(){});
推薦笆焰,可代替AnimatorListener,需要監(jiān)聽(tīng)動(dòng)畫(huà)開(kāi)始见坑,結(jié)束嚷掠,取消,重復(fù)那種就直接實(shí)現(xiàn)那種方法就行
其實(shí)AnimatorListenerAdapter的源碼只是一個(gè)實(shí)現(xiàn)了AnimatorListener接口的抽象類而已
- animator.addUpdateListener(new  ValueAnimator.AnimatorUpdateListener(){}); 
更加精確的方法來(lái)時(shí)刻監(jiān)聽(tīng)當(dāng)前動(dòng)畫(huà)的執(zhí)行情況荞驴,可以讀取到動(dòng)畫(huà)的每個(gè)更新值了

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


###Keyframes 
keyFrame是一個(gè) 時(shí)間/值 對(duì),通過(guò)它可以定義一個(gè)在特定時(shí)間的特定狀態(tài)熊楼,即關(guān)鍵幀霹娄,而且在兩個(gè)keyFrame之間可以定義不同的Interpolator,就好像多個(gè)動(dòng)畫(huà)的拼接,第一個(gè)動(dòng)畫(huà)的結(jié)束點(diǎn)是第二個(gè)動(dòng)畫(huà)的開(kāi)始點(diǎn)犬耻。KeyFrame是抽象類踩晶,要通過(guò)ofInt(),ofFloat(),ofObject()獲得適當(dāng)?shù)腒eyFrame,然后通過(guò)PropertyValuesHolder.ofKeyframe獲得PropertyValuesHolder對(duì)象枕磁,如以下例子:

/*

  • 動(dòng)畫(huà)效果:btn對(duì)象的width屬性值使其:
  • 開(kāi)始時(shí) Width=400
  • 動(dòng)畫(huà)開(kāi)始1/4時(shí) Width=200
  • 動(dòng)畫(huà)開(kāi)始1/2時(shí) Width=400
  • 動(dòng)畫(huà)開(kāi)始3/4時(shí) Width=100
  • 動(dòng)畫(huà)結(jié)束時(shí) 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' /><!--動(dòng)畫(huà)值的類型-->

</set>
- 通過(guò)AnimatorInflater.loadAnimator方法加載xml動(dòng)畫(huà)返回一個(gè)Animator的對(duì)象渡蜻,然后調(diào)用setTarget方法給動(dòng)畫(huà)設(shè)置對(duì)象調(diào)用哪個(gè)start啟動(dòng)動(dòng)畫(huà)即可完成xml動(dòng)畫(huà)效果

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



###LayoutAnimation  布局動(dòng)畫(huà)
- LayoutTransition為布局的容器設(shè)置動(dòng)畫(huà),當(dāng)容器中的視圖層次發(fā)生變化時(shí)存在過(guò)渡的動(dòng)畫(huà)效果计济。
- 過(guò)渡類型:
 - LayoutTransition.APPEARING 當(dāng)一個(gè)View在ViewGroup中出現(xiàn)時(shí)茸苇,對(duì)**此View**設(shè)置的動(dòng)畫(huà)
 - LayoutTransition.CHANGE_APPEARING 當(dāng)一個(gè)View在ViewGroup中出現(xiàn)時(shí),對(duì)此View對(duì)其他View位置造成影響沦寂,對(duì)**其他View**設(shè)置的動(dòng)畫(huà)
 - LayoutTransition.DISAPPEARING  當(dāng)一個(gè)View在ViewGroup中消失時(shí)学密,對(duì)**此View**設(shè)置的動(dòng)畫(huà)
 - LayoutTransition.CHANGE_DISAPPEARING 當(dāng)一個(gè)View在ViewGroup中消失時(shí),對(duì)此View對(duì)其他View位置造成影響传藏,對(duì)其**他View**設(shè)置的動(dòng)畫(huà)
 - LayoutTransition.CHANGE 不是由于View出現(xiàn)或消失造成對(duì)其他View位置造成影響腻暮,然后對(duì)**其他View**設(shè)置的動(dòng)畫(huà)。

- 步驟:
 1. 實(shí)例化一個(gè)LayoutTransition對(duì)象
 3. 使用setAnimator 設(shè)置LayoutTransition對(duì)象的動(dòng)畫(huà)漩氨,這個(gè)動(dòng)畫(huà)包含了上述四個(gè)類型西壮。可以使用android自帶的動(dòng)畫(huà)叫惊,也可以使用自定義動(dòng)畫(huà)款青。本例中的自定義動(dòng)畫(huà)效果和上例一樣。
  2. setLayoutTransition指定container的LayoutTransition對(duì)象
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));//可用使用自定義動(dòng)畫(huà)
    transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,
            null);
    mGridLayout.setLayoutTransition(transition);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末霍狰,一起剝皮案震驚了整個(gè)濱河市抡草,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蔗坯,老刑警劉巖康震,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宾濒,居然都是意外死亡腿短,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)绘梦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)橘忱,“玉大人,你說(shuō)我怎么就攤上這事卸奉《鄢希” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵榄棵,是天一觀的道長(zhǎng)凝颇。 經(jīng)常有香客問(wèn)我潘拱,道長(zhǎng),這世上最難降的妖魔是什么拧略? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任芦岂,我火速辦了婚禮,結(jié)果婚禮上辑鲤,老公的妹妹穿的比我還像新娘盔腔。我一直安慰自己,他們只是感情好月褥,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布弛随。 她就那樣靜靜地躺著,像睡著了一般宁赤。 火紅的嫁衣襯著肌膚如雪舀透。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天决左,我揣著相機(jī)與錄音愕够,去河邊找鬼。 笑死佛猛,一個(gè)胖子當(dāng)著我的面吹牛惑芭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播继找,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼遂跟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了婴渡?” 一聲冷哼從身側(cè)響起幻锁,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎边臼,沒(méi)想到半個(gè)月后哄尔,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柠并,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年岭接,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臼予。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亿傅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘟栖,到底是詐尸還是另有隱情,我是刑警寧澤谅阿,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布半哟,位于F島的核電站酬滤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寓涨。R本人自食惡果不足惜盯串,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望戒良。 院中可真熱鬧体捏,春花似錦、人聲如沸糯崎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)沃呢。三九已至年栓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間薄霜,已是汗流浹背某抓。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惰瓜,地道東北人否副。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像崎坊,于是被迫代替她去往敵國(guó)和親备禀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容