Android動畫效果之Property Animation(屬性動畫)

一. Property Animation產生的背景:

    由於Tween Animation(補間動畫)只能實現簡單的四種的動畫(alpha、scale、rotate、translate),要想實現比較複雜的動畫就難以滿足需求,而且補間動畫只是改變了View對象繪製的位置,而沒有改變View對象本身,比如View形狀的變換,如大小的縮放,透明度的改變,位置的改變,其實本身並沒有改變,舉個例子就好比孫悟空靈魂出竅一樣,雖然已經上天入地,其實肉體還在那裏一動不動,我們開發過程中的經常遇見的就是translate之後事件還在原地。如果要實現既要有動畫效果又要使得View本身得到真正改變,那就要藉助屬性動畫了,這也是屬性動畫引入的原因。它能夠更加靈活的實現各種效果,不僅限於類似補間動畫實現的哪幾種效果。

(1)Property Animation相關類

   屬性動畫,根據字面理解可以通過修改物件的屬性值以達到動畫效果。

類名用途
ValueAnimator屬性動畫主要的計時器,也計算動畫後的屬性的值,動畫的執行類
ObjectAnimator  ValueAnimator的一個子類,允許你設置一個目標對象和對象的屬性進行動畫,動畫的執行類
AnimatorSet提供組織動畫的結構,使它們能相關聯得運行,用於控制一組動畫的執行
AnimatorInflater 用戶加載屬性動畫的xml文件
Evaluators 屬性動畫計算器,告訴了屬性動畫系統如何計算給出屬性的值
Interpolators動畫插入器,定義動畫的變化率

(2)Interpolator(插值器)

   Interpolator插值器用於控制動畫的變化速率,也可以簡單的理解成用於控制動畫的快慢,插值器目前都只是對動畫執行過程的時間進行修飾,並沒有對軌跡進行修飾。系統提供的插值器有以下幾種:

插值器名字解說對應的xml
AccelerateInterpolator 加速,開始時慢中間加速 @android:anim/accelerate_interpolator
DecelerateInterpolator減速,開始時快然後減速@android:anim/decelerate_interpolator
AccelerateDecelerateInterolator  先加速後減速,開始結束時慢,中間加速 @android:anim/accelerate_decelerate_interpolator
AnticipateInterpolator反向 ,先向相反方向改變一段再加速播放 @android:anim/anticipate_interpolator
AnticipateOvershootInterpolator反向加超越,先向相反方向改變,再加速播放,會超出目的值然後緩慢移動至目的值@android:anim/anticipate_overshoot_interpolator
BounceInterpolator 跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次爲85,77,70,80,90,100@android:anim/bounce_interpolator
CycleIinterpolator 循環,動畫循環一定次數,值的改變爲一正弦函數:Math.sin(2* mCycles* Math.PI* input)@android:anim/cycle_interpolator
LinearInterpolator 線性,線性均勻改變@android:anim/linear_interpolator
OvershootInterpolator超越,最後超出目的值然後緩慢改變到目的值@android:anim/overshoot_interpolator

二. 使用ObjectAnimator

(1)alpha漸變效果

         1>java代碼實現

ObjectAnimator animator = ObjectAnimator.ofFloat(image, "alpha", 1.0f, 0.1f);    //綁定佈局,設置爲漸變,從1.0 --> 0.1
animator.setDuration(2000);        //設置動畫時間
animator.setRepeatCount(10);        //設置動畫顯示次數
animator.setRepeatMode(ValueAnimator.REVERSE);    //設置動畫顯示模式,反向
animator.setStartDelay(200);        //設置動畫多次顯示的時間間隔
animator.setInterpolator(new OvershootInterpolator());    //設置動畫插入器,插入器直接影響顯示結果
animator.start();                    //開始動畫

2>xml實現

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="alpha"
    android:duration="3000"
    android:repeatCount="1"
    android:repeatMode="reverse"
    android:startOffset="200"
    android:valueFrom="1.0"
    android:valueTo="0.1"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(2)scale翻轉效果(與補間動畫scale有些區別)

1>java代碼實現

ObjectAnimator animator = ObjectAnimator
        .ofFloat(image, "scaleX", 1.0f, 0.1f);  //scaleX爲Y軸不變,以view中心爲點,X軸翻轉;scaleY效果相反
animator.setDuration(2000);
animator.setRepeatCount(10);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setStartDelay(200);
animator.setInterpolator(new OvershootInterpolator());
animator.start();

2>xml實現

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="scaleX"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:valueFrom="1.0"
    android:valueTo="0.1"
    android:duration="2000"
    android:startOffset="200"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(3)rotation 旋轉效果(與補間動畫rotate書寫不一樣)

1>java代碼實現

ObjectAnimator animator = ObjectAnimator.ofFloat(image, "rotation", 0f, 360f);  //旋轉角度0 --> 360
animator.setDuration(2000);
animator.setRepeatCount(10);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setStartDelay(200);
animator.setInterpolator(new OvershootInterpolator());
animator.start();

2>xml實現

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="rotation"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:valueFrom="0f"
    android:valueTo="360f"
    android:duration="2000"
    android:startOffset="200"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(4)translation(與補間動畫translate書寫不一樣)

1>java代碼實現

//translationX,Y軸不變,水平X軸移動,0f爲屏幕中心,0f --> 480f(水平向右移動);translationY,X軸不變,水平Y軸移動
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 480f); 
animator.setDuration(2000);
animator.setRepeatCount(10);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setStartDelay(200);
animator.setInterpolator(new OvershootInterpolator());
animator.start();

2>xml實現

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="translationY"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:valueFrom="0f"
    android:valueTo="480f"
    android:duration="2000"
    android:startOffset="200"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(5)set

1>java代碼實現(旋轉向右移動)

①使用AnimatroSet實現

AnimatorSet animatorSet = new AnimatorSet();

ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 400f);
animator.setRepeatMode(ValueAnimator.REVERSE);    //動畫模式,需要單獨設置
animator.setRepeatCount(10);                      //動畫次數n+1次,需要單獨設置

ObjectAnimator animator1 = ObjectAnimator.ofFloat(image, "rotation", 0f, 360f);
animator1.setRepeatMode(ValueAnimator.REVERSE);   //動畫模式,需要單獨設置
animator1.setRepeatCount(10);                     //動畫次數n+1次,需要單獨設置

animatorSet.setDuration(2000);                    //動畫時間,可set設置
animatorSet.setStartDelay(200);                   //動畫間隔,可set設置
animatorSet.playTogether(animator,animator1);     //set添加動畫
animatorSet.setInterpolator(new OvershootInterpolator());
animatorSet.start();

②使用PropertyValuesHolder實現

PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.1f);
PropertyValuesHolder scaleYValuesHolder = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.1f);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(image, scaleXValuesHolder, scaleYValuesHolder);
objectAnimator.setDuration(2000);
objectAnimator.setRepeatCount(10);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.start();

③使用ViewPropertyAnimator實現

ViewPropertyAnimator viewPropertyAnimator=image.animate();
viewPropertyAnimator.scaleXBy(1.0f).scaleX(0.1f).alphaBy(1.0f).scaleY(0.1f).setDuration(2000).start();

2>xml實現

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:repeatCount="10"
        android:repeatMode="reverse"
        android:startOffset="200"
        android:valueFrom="0f"
        android:valueTo="400f"
        android:valueType="floatType" />
    <objectAnimator
        android:duration="2000"
        android:propertyName="rotation"
        android:repeatCount="10"
        android:repeatMode="reverse"
        android:startOffset="200"
        android:valueFrom="0f"
        android:valueTo="360f"
        android:valueType="floatType" />

</set>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

三. ObjectAnimator的監聽事件

(1)ObjectAnimator.addListener

有時候我們可能要在某一個動畫執行之前 或者動畫結束之後進行一些其他的操作

ObjectAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animator) {
        //TODO 動畫開始前的操作
        Log.i("aaaaa", "動畫開始前的操作");
    }

    @Override
    public void onAnimationEnd(Animator animator) {
        //TODO 動畫結束的操作
        Log.i("aaaaa", "動畫結束的操作");
    }

    @Override
    public void onAnimationCancel(Animator animator) {
        //TODO 動畫取消的操作
        Log.i("aaaaa", "動畫取消的操作");
    }

    @Override
    public void onAnimationRepeat(Animator animator) {
        //TODO 動畫重複的操作
        Log.i("aaaaa", "動畫重複的操作");
    }
});

(2)objectAnimator.addUpdateListener

如果我們需要簡單動畫執行過程中的變化可以使用AnimatorUpdateListener

ObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        float value = (float) animator.getAnimatedValue();
        Log.i("aaaaa", "valueAnimator : " + value);
        if (value >= 300 && value <= 320)
            Toast.makeText(AnimatorActivity.this, value + "", Toast.LENGTH_SHORT).show();
    }
});

四. ValueAnimator(差值動畫)

ValueAnimator是ObjectAnimator的父類,它繼承自抽象類Animator,它作用於一個值,將其由一個值變化爲另外一個值,然後根據值的變化,按照一定的規則,動態修改View的屬性,比如View的位置、透明度、旋轉角度、大小等,即可完成了動畫的效果。

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 12164f);
valueAnimator.setDuration(5000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        float money = (float) valueAnimator.getAnimatedValue();
        textView.setText(String.format("%.2f", money));
    }
});
valueAnimator.start();

每天進步一點點!

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