Animation動畫的解析,Animation動畫解析
Animation在View的包下,我們通過Animation的原理也可知道,Animation離開了View就沒有效果,為什麼這麼說呢?
Animation的動畫原理
我們先看一個簡單的Animation動畫,AlphaAnimation:
public class AlphaAnimation extends Animation { private float mFromAlpha; private float mToAlpha; /** * Constructor used when an AlphaAnimation is loaded from a resource. * * @param context Application context to use * @param attrs Attribute set from which to read values */ public AlphaAnimation(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation); mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f); mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f); a.recycle(); } /** * Constructor to use when building an AlphaAnimation from code * * @param fromAlpha Starting alpha value for the animation, where 1.0 means * fully opaque and 0.0 means fully transparent. * @param toAlpha Ending alpha value for the animation. */ public AlphaAnimation(float fromAlpha, float toAlpha) { mFromAlpha = fromAlpha; mToAlpha = toAlpha; } /** * Changes the alpha property of the supplied {@link Transformation} */ @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float alpha = mFromAlpha; t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime)); } @Override public boolean willChangeTransformationMatrix() { return false; } @Override public boolean willChangeBounds() { return false; } /** * @hide */ @Override public boolean hasAlpha() { return true; }}
代碼非常簡單,其核心代碼就在
@Overrideprotected void applyTransformation(float interpolatedTime, Transformation t) { final float alpha = mFromAlpha; t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));}
通過interpolatedTime來不斷給變alpha的值,我們就可以看到一個View實現透明度變化的動畫效果!那麼問題來了,誰在調用applyTransformation方法呢?跟進代碼看到
public boolean getTransformation(long currentTime, Transformation outTransformation){}
中對applyTransformation做了調用,不用想了,getTransformation肯定是在View的startAnimation觸發的!
是不是呢?
public void startAnimation(Animation animation) { animation.setStartTime(Animation.START_ON_FIRST_FRAME); setAnimation(animation); invalidateParentCaches(); invalidate(true); }
這裡重新繪製了View,所以View的boolean draw(Canvas canvas, ViewGroup parent, long drawingTime)方法會被執行,為什麼是draw而不是onDraw,我們看著麼一句註解
/** * This method is called by ViewGroup.drawChild() to have each child view draw itself. * This draw() method is an implementation detail and is not intended to be overridden or * to be called from anywhere else other than ViewGroup.drawChild(). */
而在draw()方法中有
final Animation a = getAnimation();if (a != null) { more = drawAnimation(parent, drawingTime, a, scalingRequired); concatMatrix = a.willChangeTransformationMatrix(); if (concatMatrix) { mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; } transformToApply = parent.getChildTransformation();}
所以Animation得getTransformation的到執行,這就是Animation的實現原理。
但這好像對於我們來說意義不大,確實,因為我們不是Animation的締造者,我們你只需要知道如何使用即可,就當前面熱熱身了!
Animation的使用
Animation的使用非常簡單,Android中已經為我們定義好了四種Animation動畫效果AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation
以AlphaAnimation為例快速的說明一下其使用方法:
AlphaAnimation animation = new AlphaAnimation(1,0);animation.setDuration(2000) ;animation.setRepeat(2) ;view.startAnimation(animation);
ok,一個View的動畫就實現了,其他三個動畫效果也是類似的,非常簡單!這裡不重複了,我們重點來看一下如何自己定義一個Animation效果,還是通過一個案例來說明。
實現一個按鈕放大的動畫效果,這裡放大不能出現展開,如果可以展開那就沒意義了,因為系統已經為我們定義好了一個,ScaleAnimation就可以實現;
第一步 、繼承Animation,
第二步 、重寫applyTransformation方法
第三步、沒了!
所以代碼如下:
/** * Created by moon.zhong on 2015/4/23. */public class ScaleAnimation extends Animation { private View mTarget ; private int mOriginWidth ; private int mTargetWidth; private ViewGroup.LayoutParams mParams ; public ScaleAnimation(int mTargetWidth, View target) { this.mTarget = target; this.mOriginWidth = mTarget.getMeasuredWidth(); this.mTargetWidth = mTargetWidth; if (mOriginWidth == 0 ){ mTarget.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { mTarget.getViewTreeObserver().removeOnPreDrawListener(this); mOriginWidth = mTarget.getMeasuredWidth() ; return false; } }); } mParams = target.getLayoutParams() ; } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { /*interpolatedTime * 變化範圍 * 0~1 * */ mParams.width = (int) (mOriginWidth + (mTargetWidth - mOriginWidth)*interpolatedTime) ; mTarget.setLayoutParams(mParams); }}
使用代碼:
public void startAnimation(View view){ final float density = getResources().getDisplayMetrics().density; int width = (int) (300 * density); ScaleAnimation animation = new ScaleAnimation(width,mTargetView) ; animation.setDuration(2000); mTargetView.startAnimation(animation); }
:
再來一張展開的對比:
總結:
總體來說還是非常簡單的,這裡我只是定義了一個簡單的動畫,同理定義一個複雜一點的動畫也是同樣的操作,只是applyTransformation裡面的代碼寫的多一點而已。
本篇blog的知識點主要有:
1、Animation的運用情境,作用於View中;
2、系統Animation的使用
AlphaAnimation animation = new AlphaAnimation(1,0);animation.setDuration(2000) ;animation.setRepeat(2) ;View.startAnimation(animation);
這種形式,當然還有讀取xml的形式,這裡沒有提及到
3、自訂Animation
重寫applyTransformation 方法
Demo源碼
http://download.csdn.net/detail/jxxfzgy/8634819