前面初步認識了Android的Property Animation(屬性動畫)Android動畫效果之初識Property Animation(屬性動畫)(三),而且利用屬性動畫簡單了補間動畫可以實現的動畫效果,今天重點學習下Property Animation基本原理及高級使用。本章先經過餘額寶的數字動畫小例子來學習屬性動畫基本原理。具體效果以下:html
其餘幾種動畫效果:android
上篇文章一直使用的ObjectAnimator來實現屬性動畫,單純從字面上理解的話ObjectAnimator做用於某個實際的對象,而ValueAnimator是ObjectAnimator的父類,它繼承自抽象類Animator,它做用於一個值,將其由一個值變化爲另一個值,而後根據值的變化,按照必定的規則,動態修改View的屬性,好比View的位置、透明度、旋轉角度、大小等,便可完成了動畫的效果。直接看下上面的數字動畫是怎麼實現的?設計模式
ValueAnimator valueAnimator =ValueAnimator.ofFloat( 0f, 126512.36f); valueAnimator.setDuration(2000); valueAnimator.setInterpolator(new LinearInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float money= (float) animation.getAnimatedValue(); mTextView.setText(String.format("%.2f", money)); } }); valueAnimator.start();
這裏經過ofFloat()方法構造一個ValueAnimator實例,除此以外還提供了其餘函數ofInt()、ofObject()、ofPropertyValuesHolder()函數,api 21以後又提供了ofArgb(),每一個函數都是能夠傳入多個改變值。api
Interpolator插值器用於控制動畫的變化速率,也能夠簡單的理解成用於控制動畫的快慢,插值器目前都只是對動畫執行過程的時間進行修飾,並無對軌跡進行修飾。系統提供的插值器有如下幾種:ide
插值器名字 | 解說 | 對應的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 |
經過上面的名字你們是否是很眼熟,是的和補間動畫的插值器是一致的。Android的動畫插值器採用策略設計模式,都是實現了Interpolator這個接口,而Interpolator又是繼承自一個叫作TimeInterpolator的接口(從3.0開始,增長了TimeInterpolator這個接口,並把原先的Interpolator接口的抽象方法移到了其中,3.0後的Interpolator接口也就什麼也沒作,只是對父類改了個名字,達到向下兼容)。函數
package android.animation; public interface TimeInterpolator { float getInterpolation(float input); }
在Interpolator的實現類裏面,都實現了一個float getInterpolator(float input)的方法,傳入參數是正常執行動畫的時間點,返回值是用戶真正想要它執行的時間點。上面的數字動畫使用了勻速插值器LinearInterpolator其代碼實現以下:佈局
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory { public LinearInterpolator() { } public LinearInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { return input; } /** @hide */ @Override public long createNativeInterpolator() { return NativeInterpolatorFactoryHelper.createLinearInterpolator(); } }
能夠看出float getInterpolator(float input)返回的值就是當前要執行的時間點實現勻速執行動畫。post
如何自定義一個插值器?舉例:咱們實現一個先減速後加速插值器,代碼以下學習
public class DecelerateAccelerateInterpolator implements Interpolator { @Override public float getInterpolation(float input) { float result; if (input <= 0.5f) { result = (float) (Math.sin(Math.PI * input)) / 2.0f; } else { result = (float) (2 - Math.sin(Math.PI * input)) / 2.0f; } return result; } }
TypeEvaluator用於根據當前屬性改變的百分比來計算改變後的屬性值,系統提供了以下幾種估值器字體
IntEvaluator 針對整型屬性
IntArrayEvaluator 針對整型屬性集合
FloatEvaluator 針對浮點型屬性
FloatArrayEvaluator 針對浮點型屬性集合
ArgbEvaluator 針對Color屬性
RectEvaluator 針對Rect屬性
PointFEvaluator 針對PointF屬性
TypeEvaluator設計也是採用策略設計模式,都實現TypeEvaluator接口,源代碼以下:
package android.animation; public interface TypeEvaluator<T> { public T evaluate(float fraction, T startValue, T endValue); }
接口提供了evaluate(float fraction, T startValue, T endValue);動畫在運行過程當中Interpolator自動計算出動畫運行的百分比fraction,而後TypeEvaluator根據fraction計算出當前動畫的屬性值。以FloatEvaluator 代碼爲例:
public class FloatEvaluator implements TypeEvaluator<Number> { public Float evaluate(float fraction, Number startValue, Number endValue) { float startFloat = startValue.floatValue(); return startFloat + fraction * (endValue.floatValue() - startFloat); } }
如何自定義TypeEvaLuator?好比咱們要實現一個錢的增長,字體顏色越紅的動畫,咱們如今都知道可使用ofArgb(),可是ofArgb()須要api 21以上才能使用,因此須要咱們自定義一個ArgbEvaLuator,這裏爲了演示自定義TypeEvaluator直接把api 21中提供的ArgbEvaluator源代碼拿來使用,以下:
public class TextArgbEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { int startInt = (Integer) startValue; int startA = (startInt >> 24) & 0xff; int startR = (startInt >> 16) & 0xff; int startG = (startInt >> 8) & 0xff; int startB = startInt & 0xff; int endInt = (Integer) endValue; int endA = (endInt >> 24) & 0xff; int endR = (endInt >> 16) & 0xff; int endG = (endInt >> 8) & 0xff; int endB = endInt & 0xff; return (int) ((startA + (int) (fraction * (endA - startA))) << 24) | (int) ((startR + (int) (fraction * (endR - startR))) << 16) | (int) ((startG + (int) (fraction * (endG - startG))) << 8) | (int) ((startB + (int) (fraction * (endB - startB)))); } }
調用方式:
AnimatorSet animatorSet = new AnimatorSet(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 126512.36f); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float money = (float) animation.getAnimatedValue(); Log.e("Interpolator", "money---->" + money); mTextView.setText(String.format("%.2f", money)); } }); int startColor = Color.parseColor("#FCA3AB"); int endColor = Color.parseColor("#FB0435"); ValueAnimator colorAnimator = ValueAnimator.ofObject(new TextArgbEvaluator(),startColor, endColor); colorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int color = (int) animation.getAnimatedValue(); Log.e("Interpolator", "color---->" + color); mTextView.setTextColor(color); } }); animatorSet.playTogether(valueAnimator,colorAnimator); animatorSet.setDuration(5000); animatorSet.setInterpolator(new LinearInterpolator()); animatorSet.start();
運行效果:
上篇咱們簡單了學習了ObjectAnimator動畫,而且經過ObjectAnimator實現了幾種簡單的動畫效果,ObjectAnimator繼承自ValueAnimator,因此主體方法仍是ValueAnimator裏實現的。先來回顧一下上篇的一個旋轉動畫例子。
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imageView, "rotation", 0f, 360f); objectAnimator.setDuration(500); objectAnimator.setRepeatCount(1); objectAnimator.setRepeatMode(ValueAnimator.REVERSE); objectAnimator.start();
這個例子很簡單,針對view的屬性rotation進行持續時間爲500ms的0到360的角度變換。屬性名字rotation在View中有對應setRotation(),不然沒有任何效果,並且參數類型必須爲float型,不然沒有任何效果。view常見可操做的參數有:x/y;scaleX/scaleY;rotationX/ rotationY;transitionX/ transitionY等等。如今問題來了,咱們本篇例子是爲TextView 賦值一個float型的值,咱們查看TextView的函數並不找不到setText(float f),這時該怎麼處理呢?如何爲不具備get/set方法的屬性提供修改方法呢?莫着急!谷歌爲此提供了兩種方法,第一種就是使用ValueAnimator來實現,就是上面所說的方式,另一種方式經過本身寫一個包裝類,來爲該屬性提供get/set方法。
public class MoneyTextView extends TextView { public MoneyTextView(Context context, AttributeSet attrs) { super(context, attrs); } public void setText(float money) { setText(String.format("%.2f", money)); } }
而後就能夠經過ObjectAnimator實現上面的數字動畫效果了。
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "text", 0f, 126512.36f); objectAnimator.setDuration(2000); objectAnimator.setInterpolator(new LinearInterpolator()); objectAnimator.start();
其餘有關ObjectAnimator的使用方式請參考上篇文章Android動畫效果之初識Property Animation(屬性動畫)(三)。
本篇主要簡單學習了屬性動畫的基本原理,屬性動畫使用了比較常見的策略設計模式,感興趣的話能夠看下這篇文章Java設計模式之策略模式(Strategy),下篇文章將藉助自定義ViewGroup學習一下佈局動畫。