此次主要就介紹android動畫,android動畫目前分爲三種形式,Tween Animation 這個只能應用於view對象上面的,Drawable Animation這個是幀動畫,就是相似咱們有一些列的圖片依次播放圖片時出現的動畫,Property Animation 這個是屬性動畫,這也是在android3.0以後引進的動畫,在手機的版本上是android4.0就可使用這個動畫,下面咱們主要就是針對這三種狀況進行介紹。java
Tween Animationandroid
這個動畫在Property Animation以前使用最多的,固然在android4.0以後也是有不少人使用這個動畫來弄一些簡單的動畫效果,Tween Animation主要是包括四種動畫實現效果:express
AlphaAnimation(float fromAlpha,float toAlpha)
這個就是AlphaAnimation的構造函數,fromAlpha表示的是動畫初始時的透明度,toAlpha表示的是動畫結束時的透明度,這個取值範圍是0~1,0表示的是徹底透明,1表示的是徹底不透明apache
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倍canvas
pivotXType和pivotYType分別表示在X和Y軸上伸縮模式。這裏有三個值:app
Animation.ABSOLUTE:這個表示的是絕對座標less
Animation.RELATIVE_TO_SELF:相對於本身的座標ide
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(fromXDelta, toXDelta, fromYDelta, toYDelta)
fromXDelta和fromYDelta分別表示在X和Y軸上面的起始座標,(0,0)這個表示的就是當前view的座標,toXDelta和toYDelta分別表示最終目標,若是隻是X軸移動或者Y軸移動,那麼能夠把對應不移動的座標設置爲0。
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()); } });
動畫結束以後打印的信息以下
這個時候咱們再使用x動畫以後
仍是同樣的,這個主要是由於這個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軸的動畫