一. 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();
每天進步一點點!