Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 動畫詳解

Android 動畫詳解

編輯:關於Android編程

  這個動畫在Property Animation之前使用最多的,當然在android4.0之後也是有很多人使用這個動畫來弄一些簡單的動畫效果,Tween Animation主要是包括四種動畫實現效果:       AlphaAniamtion:漸變效果,這個是一個透明度的動畫效果 1 AlphaAnimation(float fromAlpha,float toAlpha)  這個就是AlphaAnimation的構造函數,fromAlpha表示的是動畫初始時的透明度,toAlpha表示的是動畫結束時的透明度,這個取值范圍是0~1,0表示的是完全透明,1表示的是完全不透明       ScaleAnimation:圖片進行放大縮小的動畫效果, ScaleAnimation(float fromX, float toX, float fromY,float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) 上面就是這個Scale參數的情況,這個參數是最多的,fromX:起始X坐標上的伸縮尺寸,toX:結束X坐標上的伸縮尺寸,fromY:起始Y坐標上的伸縮尺寸,toY:結束Y坐標上的伸縮尺寸,關於這個伸縮尺寸,0表示的就是看不見,1表示原始大小,依此類推,1.5表示的就是1.5倍   pivotXType和pivotYType分別表示在X和Y軸上伸縮模式。這裡有三個值:   Animation.ABSOLUTE:這個表示的是絕對坐標   Animation.RELATIVE_TO_SELF:相對於自己的坐標   Animation.RELATIVE_TO_PARENT:相對於父控件   上面這些說的都是這個動畫效果相對於哪一個點來進行變化的,Animation.RELATIVE_TO_SELF這個就相對於自己的坐標,就是說這個坐標原始坐標是在你設置view的左上角,Animation.RELATIVE_TO_PARENT相對於父控件的坐標,這個大多數指的就是手機上的坐標原點。Animation.ABSOLUTE絕對坐標說的就是具體相對哪個一個點,比如(100,200),就是表示相對坐標點在(100,200)這個點來進行動畫。   pivotXValue和pivotYValue值就是相對上面的值設置的,表示的是相對於哪一個點來進行放大縮小的動畫,對於Animation.RELATIVE_TO_SELF和Animation.RELATIVE_TO_PARENT   (0,0)表示的是原點,(0.5f,0.5f)表示的中間點這個對於Animation.RELATIVE_TO_SELF相對於view控件的中間點,Animation.RELATIVE_TO_PARENT就是值該view上父控件的中間點,(1,1)表示的就是右下角的坐標。這個我們可以多多試試就知道效果了。   一般情況下使用是Animation.RELATIVE_TO_SELF,選擇點是(0.5f,0.5f)就是該view的中間點,這樣圖片變化看起來不會產生很奇怪的感覺。       TranslateAnimation:view在水平方向和垂直方向進行移動動畫效果 TranslateAnimation(fromXDelta, toXDelta, fromYDelta, toYDelta) fromXDelta和fromYDelta分別表示在X和Y軸上面的起始坐標,(0,0)這個表示的就是當前view的坐標,toXDelta和toYDelta分別表示最終目標,如果只是X軸移動或者Y軸移動,那麼可以把對應不移動的坐標設置為0。       RotateAnimation:旋轉動畫效果 RotateAnimation(fromDegrees, toDegrees, pivotXType, pivotXValue, pivotYType, pivotYValue) fromDegrees和toDegrees分別表示的起始角度和結束角度,比如(0,45)這個就是表示從默認狀態旋轉到45度的意思。剩下的參數上面已經介紹過來,比如下面的代碼:   RotateAnimation rotate=new RotateAnimation(0, 50, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); 表示就是從默認狀態旋轉到50度,旋轉的中心點就是這個view的中心點(Animation.RELATIVE_TO_SELF表示的以自身為參考點,0.5f表示就是一般)   上面介紹就是這個Tween Animation動畫效果,分別是透明度的變化,放大縮小,移動以及旋轉動畫效果,這些動畫除了上面的構造函數之外當然還有一些公共的其它方法,下面就介紹一下:   setDuration(long durationMillis) 這個表示的是設置動畫的顯示時間,就是這個動畫從初始狀態到結束狀態所需要的時間,durationMillis參數為動畫顯示時間的長短,單位是毫秒。   setStartOffset(long startOffset) 這個表示的是動畫的開始時間,startOffset表示就是動畫的開始時間,單位毫秒(有時候我們在startAnimation之後可能不希望立即取執行這個動畫,需要等待一會再進行動畫就可以使用這個   setFillAfter(boolean fillAfter) 這個表示的動畫結束之後是否保留結束的位置,這個值默認是flase表示動畫結束之後不保留動畫的位置,就是說在我們進行動畫效果結束之後又會自動恢復到原始的狀態,true表示就是保留動畫結束時的狀態,這個值一般都是要設置為true的   startAnimation(Animation animation) 這個是在view對象上使用的,表示開始進行動畫,參數就是我們上面說的那四種(注意上面的四種類型都是繼承於Animation的),比如我現在有一個ImageView對象image,那麼我現在要開始動畫時就是用imageView.startAnimation(rotateAnimation);就可以進行動畫了,   setInterpolator(Interpolator i) 這個表示的設置動畫的變化速度,這裡android提供很多類型的Interpolator類型的變化器   1。setInterpolator(new AccelerateInterpolator(float factor):這個AccelerateInterpolator表示的是加速,factor參數可以設置為加速的倍數,數值越大動畫的速度越快,當然也可以是默認的new AccelerateInterpolator()默認這個參數為1。我們來看一下源碼:   復制代碼 /**  * An interpolator where the rate of change starts out slowly and   * and then accelerates.  *  */ public class AccelerateInterpolator implements Interpolator {     private final float mFactor;     private final double mDoubleFactor;       public AccelerateInterpolator() {         mFactor = 1.0f;         mDoubleFactor = 2.0;     }          /**      * Constructor      *       * @param factor Degree to which the animation should be eased. Seting      *        factor to 1.0f produces a y=x^2 parabola. Increasing factor above      *        1.0f  exaggerates the ease-in effect (i.e., it starts even      *        slower and ends evens faster)      */     public AccelerateInterpolator(float factor) {         mFactor = factor;         mDoubleFactor = 2 * mFactor;     }          public AccelerateInterpolator(Context context, AttributeSet attrs) {         TypedArray a =             context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AccelerateInterpolator);                  mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);         mDoubleFactor = 2 * mFactor;           a.recycle();     }          public float getInterpolation(float input) {         if (mFactor == 1.0f) {             return input * input;         } else {             return (float)Math.pow(input, mDoubleFactor);         }     } } 復制代碼 上面那個就是AccelerateInterpolator的源碼,這個源碼中有兩個構造函數一個帶參數一個不帶參數的,從上面代碼中getInterpolation這個方法是最重要的,那麼跟蹤一下這個方法調用是在Animation.java類中的getTransformation()方法   復制代碼  public boolean getTransformation(long currentTime, Transformation outTransformation) {         if (mStartTime == -1) {             mStartTime = currentTime;         }           final long startOffset = getStartOffset();         final long duration = mDuration;         float normalizedTime;         if (duration != 0) {             normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) /                     (float) duration;         } else {             // time is a step-change with a zero duration             normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f;         }           final boolean expired = normalizedTime >= 1.0f;         mMore = !expired;           if (!mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);           if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) {             if (!mStarted) {                 fireAnimationStart();                 mStarted = true;                 if (USE_CLOSEGUARD) {                     guard.open("cancel or detach or getTransformation");                 }             }               if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);               if (mCycleFlip) {                 normalizedTime = 1.0f - normalizedTime;             }               final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);             applyTransformation(interpolatedTime, outTransformation);         }          。。。。。。。。。 return mMore;     } 復制代碼 上面就是getTransformation()方法,在這個方法中也看到之前設置的getStartOffset()以及mDuration等等,在下面發現這麼一句話   final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);mInterpolator對象創建也是在這個類裡面       public void setInterpolator(Interpolator i) {         mInterpolator = i;     } 看上面就是我們代碼中設置的,那麼來看看這個getInterpolation裡面參數的值,從上面源碼中知道mFillEnabled和mCycleFlip默認值都是flase,一般情況下我們都不會去設置這兩個值都是取默認值的,if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);這個設置了normalizedTime的值,就是下面要用做getInterpolation參數值,從上面的代碼中可以發現normalizedTime這個值是不小於0的,Math.max(Math.min(normalizedTime, 1.0f), 0.0f)表示取值范圍就是0~1,也就是手這個getInterpolation(float input)這個input參數的變化就是在指定的動畫事件內從0到1遞增變化。   我們來看看Interpolator這個類   復制代碼 package android.view.animation;   import android.animation.TimeInterpolator;   /**  * An interpolator defines the rate of change of an animation. This allows  * the basic animation effects (alpha, scale, translate, rotate) to be   * accelerated, decelerated, repeated, etc.  */ public interface Interpolator extends TimeInterpolator {     // A new interface, TimeInterpolator, was introduced for the new android.animation     // package. This older Interpolator interface extends TimeInterpolator so that users of     // the new Animator-based animations can use either the old Interpolator implementations or     // new classes that implement TimeInterpolator directly. } 復制代碼 再看這個TimeInterpolator類   復制代碼 /*  * Copyright (C) 2010 The Android Open Source Project  *  * Licensed under the Apache License, Version 2.0 (the "License");  * you may not use this file except in compliance with the License.  * You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */   package android.animation;   /**  * A time interpolator defines the rate of change of an animation. This allows animations  * to have non-linear motion, such as acceleration and deceleration.  */ public interface TimeInterpolator {       /**      * Maps a value representing the elapsed fraction of an animation to a value that represents      * the interpolated fraction. This interpolated value is then multiplied by the change in      * value of an animation to derive the animated value at the current elapsed animation time.      *      * @param input A value between 0 and 1.0 indicating our current point      *        in the animation where 0 represents the start and 1.0 represents      *        the end      * @return The interpolation value. This value can be more than 1.0 for      *         interpolators which overshoot their targets, or less than 0 for      *         interpolators that undershoot their targets.      */     float getInterpolation(float input); } 復制代碼 從這段代碼中我們得出結論就是所有的變化器都是繼承於Interpolator接口,而且都實現了float getInterpolation(float input);這個方法,那麼我們就要弄清楚這個getTransformation()方法在哪裡調用,我們說過StartAnimation是view對象調用那麼我們在View.java裡面       public void startAnimation(Animation animation) {         animation.setStartTime(Animation.START_ON_FIRST_FRAME);         setAnimation(animation);         invalidateParentCaches();         invalidate(true);     } 這段代碼中最後一句就是更新,看一下   復制代碼   /**      * 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().      */     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {         boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;         boolean more = false;         final boolean childHasIdentityMatrix = hasIdentityMatrix();         final int flags = parent.mGroupFlags;           if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {             parent.getChildTransformation().clear();             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;         }           Transformation transformToApply = null;         boolean concatMatrix = false;           boolean scalingRequired = false;         boolean caching;         int layerType = getLayerType();           final boolean hardwareAccelerated = canvas.isHardwareAccelerated();         if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||                 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {             caching = true;             // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList             if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;         } else {             caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;         }           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();         } else {       。。。。。。。。。。。。。。。。。。。。。。。 復制代碼 上面這段代碼中有這麼一句話 more = drawAnimation(parent, drawingTime, a, scalingRequired),這個函數就是   復制代碼     private boolean drawAnimation(ViewGroup parent, long drawingTime,             Animation a, boolean scalingRequired) {         Transformation invalidationTransform;         final int flags = parent.mGroupFlags;         final boolean initialized = a.isInitialized();         if (!initialized) {             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);             onAnimationStart();         }           final Transformation t = parent.getChildTransformation();         boolean more = a.getTransformation(drawingTime, t, 1f); 。。。。。。。。。。。。。。。。。。。。。。。。。 復制代碼     看到上面的drawAnimation方法中就有a.getTransformation(drawingTime, t, 1f);這個方法,我們也就明白了這個getTransformation()方法是在startAnimation()之後調用的。   2。setInterpolator(new AccelerateDecelerateInterpolator()):這個AccelerateDecelerateInterpolator表示的是先加速後減速的動畫   復制代碼 /**  * An interpolator where the rate of change starts and ends slowly but  * accelerates through the middle.  *   */ public class AccelerateDecelerateInterpolator implements Interpolator {     public AccelerateDecelerateInterpolator() {     }          @SuppressWarnings({"UnusedDeclaration"})     public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {     }          public float getInterpolation(float input) {         return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;     } } 復制代碼 3。setInterpolator(new DecelerateInterpolator(float factor)):這個表示的就是減速,factor和上面的加速參數是一個意思,只不過作用是相反的,也可以不帶參數new DecelerateInterpolator()這樣   復制代碼 /**  * An interpolator where the rate of change starts out quickly and   * and then decelerates.  *  */ public class DecelerateInterpolator implements Interpolator {     public DecelerateInterpolator() {     }       /**      * Constructor      *       * @param factor Degree to which the animation should be eased. Setting factor to 1.0f produces      *        an upside-down y=x^2 parabola. Increasing factor above 1.0f makes exaggerates the      *        ease-out effect (i.e., it starts even faster and ends evens slower)      */     public DecelerateInterpolator(float factor) {         mFactor = factor;     }          public DecelerateInterpolator(Context context, AttributeSet attrs) {         TypedArray a =             context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.DecelerateInterpolator);                  mFactor = a.getFloat(com.android.internal.R.styleable.DecelerateInterpolator_factor, 1.0f);                  a.recycle();     }          public float getInterpolation(float input) {         float result;         if (mFactor == 1.0f) {             result = (float)(1.0f - (1.0f - input) * (1.0f - input));         } else {             result = (float)(1.0f - Math.pow((1.0f - input), 2 * mFactor));         }         return result;     }          private float mFactor = 1.0f; } 復制代碼 4。setInterpolator(new CycleInterpolator()):動畫循環播放特定次數,速率改變沿著正弦曲線   復制代碼 /**  * Repeats the animation for a specified number of cycles. The  * rate of change follows a sinusoidal pattern.  *  */ public class CycleInterpolator implements Interpolator {     public CycleInterpolator(float cycles) {         mCycles = cycles;     }          public CycleInterpolator(Context context, AttributeSet attrs) {         TypedArray a =             context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.CycleInterpolator);                  mCycles = a.getFloat(com.android.internal.R.styleable.CycleInterpolator_cycles, 1.0f);                  a.recycle();     }          public float getInterpolation(float input) {         return (float)(Math.sin(2 * mCycles * Math.PI * input));     }          private float mCycles; } 復制代碼 5。setInterpolator(new LinearInterpolator()):表示勻速   復制代碼 /**  * An interpolator where the rate of change is constant  *  */ public class LinearInterpolator implements Interpolator {       public LinearInterpolator() {     }          public LinearInterpolator(Context context, AttributeSet attrs) {     }          public float getInterpolation(float input) {         return input;     } } 復制代碼 6。setInterpolator(new OvershootInterpolator()) 超越,最後超出目的值然後緩慢改變到目的值       復制代碼 /**  * An interpolator where the change flings forward and overshoots the last value  * then comes back.  */ public class OvershootInterpolator implements Interpolator {     private final float mTension;       public OvershootInterpolator() {         mTension = 2.0f;     }       /**      * @param tension Amount of overshoot. When tension equals 0.0f, there is      *                no overshoot and the interpolator becomes a simple      *                deceleration interpolator.      */     public OvershootInterpolator(float tension) {         mTension = tension;     }       public OvershootInterpolator(Context context, AttributeSet attrs) {         TypedArray a = context.obtainStyledAttributes(attrs,                 com.android.internal.R.styleable.OvershootInterpolator);           mTension =                 a.getFloat(com.android.internal.R.styleable.OvershootInterpolator_tension, 2.0f);           a.recycle();     }       public float getInterpolation(float t) {         // _o(t) = t * t * ((tension + 1) * t + tension)         // o(t) = _o(t - 1) + 1         t -= 1.0f;         return t * t * ((mTension + 1) * t + mTension) + 1.0f;     } } 復制代碼 7。setInterpolator(new BounceInterpolator()):跳躍,快到目的值時值會跳躍,如目的值100,後面的值可能依次為85,77,70,80,90,100   復制代碼 /**  * An interpolator where the change bounces at the end.  */ public class BounceInterpolator implements Interpolator {     public BounceInterpolator() {     }       @SuppressWarnings({"UnusedDeclaration"})     public BounceInterpolator(Context context, AttributeSet attrs) {     }       private static float bounce(float t) {         return t * t * 8.0f;     }       public float getInterpolation(float t) {         // _b(t) = t * t * 8         // bs(t) = _b(t) for t < 0.3535         // bs(t) = _b(t - 0.54719) + 0.7 for t < 0.7408         // bs(t) = _b(t - 0.8526) + 0.9 for t < 0.9644         // bs(t) = _b(t - 1.0435) + 0.95 for t <= 1.0         // b(t) = bs(t * 1.1226)         t *= 1.1226f;         if (t < 0.3535f) return bounce(t);         else if (t < 0.7408f) return bounce(t - 0.54719f) + 0.7f;         else if (t < 0.9644f) return bounce(t - 0.8526f) + 0.9f;         else return bounce(t - 1.0435f) + 0.95f;     } } 復制代碼     8。setInterpolator(new AnticipateOvershootInterpolator()):反向加超越,先向相反方向改變,再加速播放,會超出目的值然後緩慢移動至目的值   復制代碼 /**  * An interpolator where the change starts backward then flings forward and overshoots  * the target value and finally goes back to the final value.  */ public class AnticipateOvershootInterpolator implements Interpolator {     private final float mTension;       public AnticipateOvershootInterpolator() {         mTension = 2.0f * 1.5f;     }       /**      * @param tension Amount of anticipation/overshoot. When tension equals 0.0f,      *                there is no anticipation/overshoot and the interpolator becomes      *                a simple acceleration/deceleration interpolator.      */     public AnticipateOvershootInterpolator(float tension) {         mTension = tension * 1.5f;     }       /**      * @param tension Amount of anticipation/overshoot. When tension equals 0.0f,      *                there is no anticipation/overshoot and the interpolator becomes      *                a simple acceleration/deceleration interpolator.      * @param extraTension Amount by which to multiply the tension. For instance,      *                     to get the same overshoot as an OvershootInterpolator with      *                     a tension of 2.0f, you would use an extraTension of 1.5f.      */     public AnticipateOvershootInterpolator(float tension, float extraTension) {         mTension = tension * extraTension;     }       public AnticipateOvershootInterpolator(Context context, AttributeSet attrs) {         TypedArray a = context.obtainStyledAttributes(attrs, AnticipateOvershootInterpolator);           mTension = a.getFloat(AnticipateOvershootInterpolator_tension, 2.0f) *                 a.getFloat(AnticipateOvershootInterpolator_extraTension, 1.5f);           a.recycle();     }       private static float a(float t, float s) {         return t * t * ((s + 1) * t - s);     }       private static float o(float t, float s) {         return t * t * ((s + 1) * t + s);     }       public float getInterpolation(float t) {         // a(t, s) = t * t * ((s + 1) * t - s)         // o(t, s) = t * t * ((s + 1) * t + s)         // f(t) = 0.5 * a(t * 2, tension * extraTension), when t < 0.5         // f(t) = 0.5 * (o(t * 2 - 2, tension * extraTension) + 2), when t <= 1.0         if (t < 0.5f) return 0.5f * a(t * 2.0f, mTension);         else return 0.5f * (o(t * 2.0f - 2.0f, mTension) + 2.0f);     } } 復制代碼 9。setInterpolator(new AnticipateInterpolator()):反向 ,先向相反方向改變一段再加速播放   復制代碼 /**  * An interpolator where the change starts backward then flings forward.  */ public class AnticipateInterpolator implements Interpolator {     private final float mTension;       public AnticipateInterpolator() {         mTension = 2.0f;     }       /**      * @param tension Amount of anticipation. When tension equals 0.0f, there is      *                no anticipation and the interpolator becomes a simple      *                acceleration interpolator.      */     public AnticipateInterpolator(float tension) {         mTension = tension;     }       public AnticipateInterpolator(Context context, AttributeSet attrs) {         TypedArray a = context.obtainStyledAttributes(attrs,                 com.android.internal.R.styleable.AnticipateInterpolator);           mTension =                 a.getFloat(com.android.internal.R.styleable.AnticipateInterpolator_tension, 2.0f);           a.recycle();     }       public float getInterpolation(float t) {         // a(t) = t * t * ((tension + 1) * t - tension)         return t * t * ((mTension + 1) * t - mTension);     } } 復制代碼 就上面這麼多了,按照上面的代碼我們也可以自定義我們符合我們自己的Interpolator,定義方法就是寫一個類繼承於Interpolator接口,並且去實現getInterpolation()方法,在該方法裡面做相應的運算。   常用的方法就上面這些,來看一下一個ScaleAnimation用法,其它類似:   復制代碼     private ScaleAnimation scale(){         ScaleAnimation scaleAnimation=new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);         scaleAnimation.setDuration(1000);         scaleAnimation.setStartOffset(0);         scaleAnimation.setInterpolator(new AccelerateInterpolator());         scaleAnimation.setFillAfter(true);         return scaleAnimation;     } 復制代碼  開啟這個動畫在一個按鈕上面   復制代碼         imageView=(ImageView) findViewById(R.id.image);         scaleBtn.setOnClickListener(new OnClickListener() {                          @Override             public void onClick(View v) {                 // TODO Auto-generated method stub                 imageView.startAnimation(scale());             }         }); 復制代碼 上面這個就實現圖片放大縮小的效果   如果我們想要實現兩種以上的動畫如何處理呢,這個時候我們就可以使用AnimationSet這個類實現多個動畫疊加效果,       AnimationSet(boolean shareInterpolator);     這個參數設為false表示可以在每個添加到AnimationSet中的Animation都使用Interpolator,且效果都能清楚的觀察。設置為true如果在添加到AnimationSet中的Animation設置Interpolator將無效果,通過設置AnimationSet的Interpolator可以設置所有動畫的Interpolator且所有動畫的Interpolator都一樣。   復制代碼     private AnimationSet allAnimation(){         AnimationSet set=new AnimationSet(boolean shareInterpolator);         TranslateAnimation translate=new TranslateAnimation(0, 100, 0, 100);         RotateAnimation rotate=new RotateAnimation(0, 50, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);         set.addAnimation(translate);         set.addAnimation(rotate);         set.setInterpolator(new AnticipateOvershootInterpolator());         set.setFillAfter(true);         set.setDuration(1000);         set.setStartOffset(100);         return set;              } 復制代碼 我們看到addAnimation就是添加動畫效果,其它方法和那個是一樣的   我們在使用的過程有時候需要監聽動畫的開始和結束,AnimationListener這個就是動畫監聽   復制代碼         set.setAnimationListener(new AnimationListener() {                          @Override             public void onAnimationStart(Animation animation) {                 // TODO Auto-generated method stub                              }                          @Override             public void onAnimationRepeat(Animation animation) {                 // TODO Auto-generated method stub                              }                          @Override             public void onAnimationEnd(Animation animation) {                 // TODO Auto-generated method stub                              }         }); 復制代碼 看上面的意思就會明白那個是表示動畫的開始,那個是動畫結束了   這個我們可以在res/anim目錄中通過xml來寫動畫   復制代碼 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android">     <alpha          android:fromAlpha="0"         android:toAlpha="1"         android:duration="1000"         />     <translate          android:interpolator="@android:anim/accelerate_decelerate_interpolator"         android:fromXDelta="0"         android:toXDelta="100"         android:fromYDelta="0"         android:toYDelta="100"         android:startOffset="50"         android:duration="1000"         />   </set> 復制代碼 上面就是xml寫的,那麼如何加載呢?看下面的代碼                   Animation an=AnimationUtils.loadAnimation(AnimationTest.this, R.anim.itchqanimator);                 imageView.startAnimation(an); 這個就是加載xml裡面的動畫的   Property Animation   這個是屬性動畫,是android4.0引入手機中(android 3.0中就有了只是3.0主要的在平板電腦上使用的),我們上面講解的那種tween Animation動畫改變的是view繪制,而沒有改變View對象本身,比如,你有一個Button,坐標 (100,100),Width:200,Height:50,而你有一個動畫使其變為Width:100,Height:100,你會發現動畫過程中觸 發按鈕點擊的區域仍是(100,100)-(300,150)。而在Property Animation中,改變的是對象的實際屬性,而且Property Animation不止可以應用於View,還可以應用於任何對象。   ValueAnimator類就是這個的包含Property Animation的動畫所以核心功能,如動畫的時間,開始,結束的屬性值等等,當時對於ValueAnimator來說我們一般都不會直接使用這個,我們都是直接使用ValueAnimator的子類就是ObjectAnimator。   ObjectAnimator是繼承於ValueAnimator的,使用這個ObjectAnimator是有條件限制的   1。對象應該有一個setter函數:set<PropertyName>(駝峰命名法),這個命名法可以上網查一下,很容易理解的   2。創建ObjectAnimation對象一般是   ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(valueBtn, "alpha", 1f,0f); 像ofFloat之類的工場方法,第一個參數為對象名(這個也就是我們的view類了),第二個為屬性名,後面的參數為可變參 數,如果values…參數只設置了一個值的話,那麼會假定為目的值,屬性值的變化范圍為當前值到目的值,為了獲得當前值,該對象要有相應屬性的 getter方法:get<PropertyName>   3。如果有getter方法,其應返回值類型應與相應的setter方法的參數類型一致。正常情況駝峰命名法都是get和set方法對應的出現   復制代碼         valueBtn=(Button) findViewById(R.id.valueAnimation);         valueBtn.setOnClickListener(new OnClickListener() {                          @Override             public void onClick(View v) {                 // TODO Auto-generated method stub                 ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(valueBtn, "alpha", 1f,0f);                 objectAnimator.setDuration(1000);                 objectAnimator.start();             }         }); 復制代碼 這個就是ObjectAnimator簡單的用法,通過這個我們也可以監聽動畫的開始和結束,上面有介紹過AnimatorListener的監聽,如下:   復制代碼         objectAnimator.addListener(new AnimatorListener() {                          @Override             public void onAnimationStart(Animator animation) {                 // TODO Auto-generated method stub                              }                          @Override             public void onAnimationRepeat(Animator animation) {                 // TODO Auto-generated method stub                              }                          @Override             public void onAnimationEnd(Animator animation) {                 // TODO Auto-generated method stub                              }                          @Override             public void onAnimationCancel(Animator animation) {                 // TODO Auto-generated method stub                              }         }); 復制代碼 當是我們有時候不需要取監聽動畫的取消或者重復,這些代碼在這裡顯然是多余的,這個時候我們就可以使用AnimatorListenerAdapter這個適配器來進行監聽了,如下   復制代碼         objectAnimator.addListener(new AnimatorListenerAdapter() {               @Override             public void onAnimationEnd(Animator animation) {                 // TODO Auto-generated method stub                 super.onAnimationEnd(animation);             }               @Override             public void onAnimationStart(Animator animation) {                 // TODO Auto-generated method stub                 super.onAnimationStart(animation);             }                      }); 復制代碼 這個就只關心我們的動畫開始和介紹,其它就不需要了,代碼看起來簡潔了很多。ObjectAnimator當然也有setInterpolator()和setStartDelay()等一系列方法,這些的話就和我們上面的說的tween Animation動畫方法是一樣的。如果我們想要同時實現很多個動畫就需要AnimatorSet這個類來實現,如下代碼:   復制代碼         AnimatorSet set=new AnimatorSet();         ObjectAnimator alphaAnimator=ObjectAnimator.ofFloat(valueBtn, "alpha", 0f,1f);                       ObjectAnimator  xAnimator=ObjectAnimator.ofFloat(valueBtn, "translationX", 0f,5f,10f);                  ObjectAnimator  yAnimator=ObjectAnimator.ofFloat(valueBtn, "translationY", 0f,5f,10f);                  ObjectAnimator  rotateYAnimator=ObjectAnimator.ofFloat(valueBtn, "rotationX", 0f,90f);                  set.play(alphaAnimator).before(xAnimator);         set.play(xAnimator).with(yAnimator);         set.play(yAnimator).after(rotateYAnimator);         set.setDuration(2000);         set.start(); 復制代碼     上面就是使用AnimatorSet方法,這個方法提供了before,with,after方法,按上面代碼的意思就是alphaAnimator先執行,之後到xAnimator,yAnimator和xAnimator是同時執行的,執行完yAnimator和xAnimator之後就執行rotateYAnimator,看上面的字面意思也很容易理解了。   在實現過程中經常使用一些動畫屬性:   1。translationX,translationY,x,y 這些translationX和x,TranslationY和y是用區別的,下面來看看這個區別在哪裡(我們這裡以X坐標為例)           valueBtn=(Button) findViewById(R.id.valueAnimation);         Log.i("itchq", "valueBtn.getLeft()="+valueBtn.getLeft());         Log.i("itchq", "valueBtn.getX()="+valueBtn.getX());         Log.i("itchq", "valueBtn.getTranslationX()="+valueBtn.getTranslationX());   上面的代碼中看一默認打印的信息是:       這個默認都是為0的,當我使用translationX動畫之後 復制代碼                 ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(valueBtn, "translationX", 0f,100f);                 objectAnimator.setDuration(1000);                 objectAnimator.start();                 objectAnimator.addListener(new AnimatorListenerAdapter() {                       @Override                     public void onAnimationEnd(Animator animation) {                         // TODO Auto-generated method stub                         Log.i("itchq", "valueBtn.getLeft()="+valueBtn.getLeft());                         Log.i("itchq", "valueBtn.getX()="+valueBtn.getX());                         Log.i("itchq", "valueBtn.getTranslationX()="+valueBtn.getTranslationX());                     }                                      });     還是一樣的,這個主要是因為這個getLeft為0,那麼我們這個時候把getLeft設置為20時,當是translationX時動畫之後打出的log是   這個時候的x不再是100了而是120了,再設置為x,看一下結果   這個時候的getTranslationX()不再是100了,而是80,所以無論啥樣應用動畫,getLeft的值是不會變的,而TranslationX的值是為最終位置於布局時初始位置的差,即“最終位置-getLeft()",而x為最終位置之和,即”getLeft()+getTranslationX()“,所以當getLeft為0的時候就會發現兩個值是相等的。   2。rotation,rotationX,rotationY:旋轉,rotation用於2D旋轉角度,3D中用到後兩個   3。scaleX,scaleY:縮放   4。alpha:透明度       Keyframe   keyFrame是一個 時間/值 對,通過它可以定義一個在特定時間的特定狀態,而且在兩個keyFrame之間可以定義不同的Interpolator,就相當多個動畫的拼接,第一個動 畫的結束點是第二個動畫的開始點。KeyFrame是抽象類,要通過ofInt(),ofFloat(),ofObject()獲得適當的 KeyFrame,然後通過PropertyValuesHolder.ofKeyframe獲得PropertyValuesHolder對象,如以下代碼:   復制代碼         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 widthAnim = ObjectAnimator.ofPropertyValuesHolder(valueBtn, pvhRotation);         widthAnim.setDuration(2000);         widthAnim.start(); 復制代碼     上述代碼的意思為:設置valueBtn對象的width屬性值使其: 開始時 Width=400 動畫開始1/4時 Width=200 動畫開始1/2時 Width=400 動畫開始3/4時 Width=100 動畫結束時 Width=500   第一個參數為時間百分比,第二個參數是在第一個參數的時間時的屬性值。定義了一些Keyframe後,通過PropertyValuesHolder類的方法ofKeyframe封裝,然後通過ObjectAnimator.ofPropertyValuesHolder獲得Animator。     PropertyValuesHolder   如果需要對一個View的多個屬性進行動畫可以用ViewPropertyAnimator類,該類對多屬性動畫進行了優化,會合並一些invalidate()來減少刷新視圖           PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);         PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);         ObjectAnimator x_yAnimator=ObjectAnimator.ofPropertyValuesHolder(valueBtn, pvhX, pvhY);         x_yAnimator.setDuration(1000);         x_yAnimator.start(); 上面這段代碼就是同時進行X軸和Y軸的動畫          
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved