久久福利_99r_国产日韩在线视频_直接看av的网站_中文欧美日韩_久久一

您的位置:首頁技術(shù)文章
文章詳情頁

Android動畫機制全解析

瀏覽:73日期:2022-09-27 17:24:40
 導(dǎo)論

本文著重講解Android3.0后推出的屬性動畫框架Property Animation——Animator。

 產(chǎn)生原因

3.0之前已有的動畫框架——Animation存在一些局限性, Animation框架定義了透明度,旋轉(zhuǎn),縮放和位移幾種常見的動畫,而且控制的是整個View,實現(xiàn)原理是每次繪制視圖時View所在的ViewGroup中的drawChild函數(shù)獲取該View的Animation的Transformation值,然后調(diào)用canvas.concat(transformToApply.getMatrix()),通過矩陣運算完成動畫幀,如果動畫沒有完成,繼續(xù)調(diào)用invalidate()函數(shù),啟動下次繪制來驅(qū)動動畫,動畫過程中的幀之間間隙時間是繪制函數(shù)所消耗的時間,可能會導(dǎo)致動畫消耗比較多的CPU資源,最重要的是,動畫改變的只是顯示,并不能相應(yīng)事件。

而在Animator框架中使用最多的是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator進行更精細化控制,只控制一個對象的一個屬性值,多個ObjectAnimator組合到AnimatorSet形成一個動畫。而且ObjectAnimator能夠自動驅(qū)動,可以調(diào)用setFrameDelay(longframeDelay)設(shè)置動畫幀之間的間隙時間,調(diào)整幀率,減少動畫過程中頻繁繪制界面,而在不影響動畫效果的前提下減少CPU資源消耗。因此,Anroid推出的強大的屬性動畫框架,基本可以實現(xiàn)所有的動畫效果。

 強大的原因

因為屬性動畫框架操作的是真實的屬性值,直接變化了對象的屬性,因此可以很靈活的實現(xiàn)各種效果,而不局限于以前的4種動畫效

Android動畫機制全解析

 ObjectAnimator

ObjectAnimator是屬性動畫框架中最重要的實行類,創(chuàng)建一個ObjectAnimator只需通過他的靜態(tài)工廠類直接返回一個ObjectAnimator對象。傳的參數(shù)包括一個對象和對象的屬性名字,但這個屬性必須有g(shù)et和set函數(shù),內(nèi)部會通過java反射機制來調(diào)用set函數(shù)修改對象屬性值。還包括屬性的初始值,最終值,還可以調(diào)用setInterpolator設(shè)置曲線函數(shù)。

ObjectAnimator實例

ObjectAnimator.ofFloat(view, "rotationX", 0.0F, 360.0F).setDuration(1000).start();

這個例子很簡單,針對view的屬性rotationX進行持續(xù)時間為1000ms的0到360的角度變換。

PS:可操縱的屬性參數(shù):x/y;scaleX/scaleY;rotationX/ rotationY;transitionX/ transitionY等等。

PS:X是View最終的位置、translationX為最終位置與布局時初始位置的差。所以若就用translationX即為在原來基礎(chǔ)上移動多少,X為最終多少。getX()的值為getLeft()與getTranslationX()的和。

動畫繪制過程的監(jiān)聽

animator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator arg0) {}});

該方法用來監(jiān)聽動畫繪制過程中的每一幀的改變,通過這個方法,我們可以在動畫重繪的過程中,實現(xiàn)自己的邏輯。

 同時修改多個屬性值

當(dāng)然這個可以使用Animationset來實現(xiàn),這里我們使用一種取巧的方法來實現(xiàn):

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "xxx", 1.0F, 0.0F).setDuration(500);anim.start();anim.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {floatcVal = (Float) animation.getAnimatedValue();view.setAlpha(cVal);view.setScaleX(cVal);view.setScaleY(cVal);}});

我們可以監(jiān)聽一個并不存在的屬性,而在監(jiān)聽動畫更新的方法中,去修改view的屬性,監(jiān)聽一個不存在的屬性的原因就是,我們只需要動畫的變化值,通過這個值,我們自己來實現(xiàn)要修改的效果,實際上,更直接的方法,就是使用ValueAnimator來實現(xiàn),其實ObjectAnimator就是ValueAnimator的子類,這個在下面會具體講到。

 為不具有g(shù)et/set方法的屬性提供修改方法

Google在應(yīng)用層為我們提供了2種解決方法,一種是通過自己寫一個包裝類,來為該屬性提供get/set方法,還有一種是通過ValueAnimator來實現(xiàn),ValueAnimator的方法我們在下面會具體講解,這里講解下如何使用自定義的包裝類來給屬性提供get/set方法。

包裝類

private static class WrapperView {private View mTarget;public WrapperView(View target) {mTarget = target;}public int getWidth() {return mTarget.getLayoutParams().width;}public void setWidth(int width) {mTarget.getLayoutParams().width = width;mTarget.requestLayout();}}

使用方法:

ViewWrapper wrapper = new ViewWrapper(mButton);ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();

這樣就間接給他加上了get/set方法,從而可以修改其屬性實現(xiàn)動畫效果。

 多動畫效果的另一種實現(xiàn)方法——propertyValuesHolder

public void propertyValuesHolder(View view) {PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,0f, 1f);PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,0, 1f);PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,0, 1f);ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(1000).start();} ValueAnimator

說簡單點,ValueAnimator就是一個數(shù)值產(chǎn)生器,他本身不作用于任何一個對象,但是可以對產(chǎn)生的值進行動畫處理。

ValueAnimator animator = ValueAnimator.ofFloat(0, 100);animator.setTarget(view);animator.setDuration(1000).start();animator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Float value = (Float) animation.getAnimatedValue();imageView.setTranslationY(value);}});

通過這個動畫我們可以發(fā)現(xiàn),和我們在上面提供的使用ObjectAnimator的方法很像,的確,我前面說這個才是專業(yè)的寫法,就是這個原因,動畫生成的原理就是通過差值器計算出來的一定規(guī)律變化的數(shù)值作用到對象上來實現(xiàn)對象效果的變化,因此我們可以使用ObjectAnimator來生成這些數(shù),然后在動畫重繪的監(jiān)聽中,完成自己的效果。

ValueAnimator是計算動畫過程中變化的值,包含動畫的開始值,結(jié)束值,持續(xù)時間等屬性。但并沒有把這些計算出來的值應(yīng)用到具體的對象上面,所以也不會有什么的動畫顯示出來。要把計算出來的值應(yīng)用到對象上,必須為ValueAnimator注冊一個監(jiān)聽器ValueAnimator.AnimatorUpdateListener,該監(jiān)聽器負責(zé)更新對象的屬性值。在實現(xiàn)這個監(jiān)聽器的時候,可以通過getAnimatedValue()的方法來獲取當(dāng)前幀的值。

ValueAnimator封裝了一個TimeInterpolator,TimeInterpolator定義了屬性值在開始值與結(jié)束值之間的插值方法。ValueAnimator還封裝了一個TypeAnimator,根據(jù)開始、結(jié)束值與TimeIniterpolator計算得到的值計算出屬性值。ValueAnimator根據(jù)動畫已進行的時間跟動畫總時間(duration)的比計算出一個時間因子(0~1),然后根據(jù)TimeInterpolator計算出另一個因子,最后TypeAnimator通過這個因子計算出屬性值,例如在10ms時(total 40ms):

首先計算出時間因子,即經(jīng)過的時間百分比:t=10ms/40ms=0.25

經(jīng)插值計算(inteplator)后的插值因子:大約為0.15,如果使用了AccelerateDecelerateInterpolator,計算公式為(input即為時間因子):

(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

最后根據(jù)TypeEvaluator計算出在10ms時的屬性值:0.15*(40-0)=6pixel。如果使用TypeEvaluator為FloatEvaluator,計算方法為 :

public Float evaluate(float fraction, Number startValue, Number endValue) {float startFloat = startValue.floatValue();return startFloat + fraction * (endValue.floatValue() - startFloat);}

參數(shù)分別為上一步的插值因子,開始值與結(jié)束值。

 ValueAnimator與ObjectAnimator實例

package com.example.animtest;import android.animation.TypeEvaluator;import android.animation.ValueAnimator;import android.animation.ValueAnimator.AnimatorUpdateListener;import android.app.Activity;import android.graphics.PointF;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.view.animation.BounceInterpolator;import android.view.animation.LinearInterpolator;import android.widget.ImageView;public class AnimateFreeFall extends Activity {private int screenHeight;private int screenWidth;private ImageView imageView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(R.layout.animate_free_fall);DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);screenHeight = metrics.heightPixels;screenWidth = metrics.widthPixels;imageView = (ImageView) findViewById(R.id.im);}public void clean(View view) {imageView.setTranslationX(0);imageView.setTranslationY(0);}public void freefall(View view) {final ValueAnimator animator = ValueAnimator.ofFloat(0, screenHeight- imageView.getHeight());animator.setTarget(view);animator.setInterpolator(new BounceInterpolator());animator.setDuration(1000).start();animator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {Float value = (Float) animation.getAnimatedValue();imageView.setTranslationY(value);}});}public void parabola(View view) {ValueAnimator animator = ValueAnimator.ofObject(new TypeEvaluator<PointF>() {@Overridepublic PointF evaluate(float fraction, PointF arg1,PointF arg2) {PointF p = new PointF();p.x = fraction * screenWidth;p.y = fraction * fraction * 0.5f * screenHeight * 4f* 0.5f;return p;}}, new PointF(0, 0));animator.setDuration(800);animator.setInterpolator(new LinearInterpolator());animator.start();animator.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animator) {PointF p = (PointF) animator.getAnimatedValue();imageView.setTranslationX(p.x);imageView.setTranslationY(p.y);}});}}

效果如下圖:

Android動畫機制全解析

有一點需要注意的是,由于ofInt,ofFloat等無法使用,我們自定義了一個TypeValue,每次根據(jù)當(dāng)前時間返回一個PointF對象,(PointF和Point的區(qū)別就是x,y的單位一個是float,一個是int point float的意思)PointF中包含了x,y的當(dāng)前位置,然后在更新監(jiān)聽中更新。

自定義TypeEvaluator傳入的泛型可以根據(jù)自己的需求,自己設(shè)計個Bean。

 動畫事件的監(jiān)聽

通過監(jiān)聽這個事件在屬性的值更新時執(zhí)行相應(yīng)的操作,對于ValueAnimator一般要監(jiān)聽此事件執(zhí)行相應(yīng)的動作,不然Animation沒意義(但是可用于計時),在ObjectAnimator(繼承自ValueAnimator)中會自動更新屬性,所以不必監(jiān)聽。在函數(shù)中會傳遞一個ValueAnimator參數(shù),通過此參數(shù)的getAnimatedValue()取得當(dāng)前動畫屬性值。

PS:根據(jù)應(yīng)用動畫的對象或?qū)傩缘牟煌赡苄枰趏nAnimationUpdate函數(shù)中調(diào)用invalidate()函數(shù)刷新視圖通過動畫的各種狀態(tài),我們可以監(jiān)聽動畫的各種狀態(tài)。

ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f);anim.addListener(new AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {}@Overridepublic void onAnimationCancel(Animator animation) {}});anim.start();

可以看見,API提供了開始、重復(fù)、結(jié)束、取消等各種狀態(tài)的監(jiān)聽,同時,API還提供了一種簡單的監(jiān)聽方法,可以不用監(jiān)聽所有的事件:

anim.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {}});

通過AnimatorListenerAdapter來選擇你需要監(jiān)聽的事件

動畫監(jiān)聽的實例應(yīng)用

package com.example.animtest;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.ObjectAnimator;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.ImageView;public class AnimateMoveInSecond extends Activity {private ImageView imageView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.animate_move_in_second);imageView = (ImageView) findViewById(R.id.imageView1);}public void doit(View view) {ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha",1.0f, 0f);animator.setDuration(1000);animator.start();animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {super.onAnimationEnd(animation);ObjectAnimator animator = ObjectAnimator.ofFloat(imageView,"alpha", 0f, 1.0f);animator.setDuration(1000);animator.start();imageView.setTranslationY(400);}});}}

效果如下圖:

Android動畫機制全解析

 AnimatorSet

AnimatorSet用于實現(xiàn)多個動畫的協(xié)同作用。效果如下:

Android動畫機制全解析

ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView, "scaleX",1f, 2f);ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView, "scaleY",1f, 2f);ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageView,"translationY", 0f, 500f);AnimatorSet set = new AnimatorSet();set.setDuration(1000);set.playTogether(animator1, animator2, animator3);set.start();

AnimatorSet中有一系列的順序控制方法:playTogether、playSequentially、animSet.play().with()、defore()、after()等。用來實現(xiàn)多個動畫的協(xié)同工作方式。

 使用xml來創(chuàng)建動畫

屬性動畫于以前的動畫一樣,也支持通過xml文件來創(chuàng)建動畫,下面是一個簡單的例子:

<?xml version="1.0" encoding="utf-8"?><objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:propertyName="scaleX"android:valueFrom="1.0"android:valueTo="2.0"android:valueType="floatType" ></objectAnimator>

public void scaleX(View view){// 加載動畫Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex);anim.setTarget(mMv);anim.start();} 布局動畫

布局動畫是指ViewGroup在布局時產(chǎn)生的動畫效果

LayoutTransition動畫

通過LayoutTransition來實現(xiàn)容器在添加子view的時候的動畫過渡效果:

Android動畫機制全解析

package com.example.animtest;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.Keyframe;import android.animation.LayoutTransition;import android.animation.ObjectAnimator;import android.animation.PropertyValuesHolder;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.LinearLayout;public class AnimateLayoutTransition extends Activity {private LinearLayout ll;private LayoutTransition mTransition = new LayoutTransition();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.animate_layout_transition);ll = (LinearLayout) findViewById(R.id.ll);setupCustomAnimations();ll.setLayoutTransition(mTransition);}public void add(View view) {final Button button = new Button(this);ll.addView(button);button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {ll.removeView(button);}});}// 生成自定義動畫private void setupCustomAnimations() {// 動畫:CHANGE_APPEARING// Changing while AddingPropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0,1);PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom",0, 1);PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",1f, 0f, 1f);PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY",1f, 0f, 1f);final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX,pvhScaleY).setDuration(mTransition.getDuration(LayoutTransition.CHANGE_APPEARING));mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);changeIn.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();// View也支持此種動畫執(zhí)行方式了view.setScaleX(1f);view.setScaleY(1f);}});// 動畫:CHANGE_DISAPPEARING// Changing while RemovingKeyframe kf0 = Keyframe.ofFloat(0f, 0f);Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);Keyframe kf2 = Keyframe.ofFloat(1f, 0f);PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight,pvhBottom, pvhRotation).setDuration(mTransition.getDuration(LayoutTransition.CHANGE_DISAPPEARING));mTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);changeOut.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setRotation(0f);}});// 動畫:APPEARING// AddingObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,0f).setDuration(mTransition.getDuration(LayoutTransition.APPEARING));mTransition.setAnimator(LayoutTransition.APPEARING, animIn);animIn.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setRotationY(0f);}});// 動畫:DISAPPEARING// RemovingObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f,90f).setDuration(mTransition.getDuration(LayoutTransition.DISAPPEARING));mTransition.setAnimator(LayoutTransition.DISAPPEARING, animOut);animOut.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator anim) {View view = (View) ((ObjectAnimator) anim).getTarget();view.setRotationX(0f);}});}}

上面的例子中自定義了 LayoutTransition來修改默認的過渡動畫,如果保持默認則使用系統(tǒng)默認的動畫效果。

過渡的類型一共有四種:

LayoutTransition.APPEARING 當(dāng)一個View在ViewGroup中出現(xiàn)時,對此View設(shè)置的動畫

LayoutTransition.CHANGE_APPEARING當(dāng)一個View在ViewGroup中出現(xiàn)時,對此View對其他View位置造成影響,對其他View設(shè)置的動畫

LayoutTransition.DISAPPEARING當(dāng)一個View在ViewGroup中消失時,對此View設(shè)置的動畫

LayoutTransition.CHANGE_DISAPPEARING當(dāng)一個View在ViewGroup中消失時,對此View對其他View位置造成影響,對其他View設(shè)置的動畫

LayoutTransition.CHANGE 不是由于View出現(xiàn)或消失造成對其他View位置造成影響,然后對其他View設(shè)置的動畫。

注意動畫到底設(shè)置在誰身上,此View還是其他View。

AnimateLayoutChanges動畫

ViewGroup的xml屬性中有一個默認的animateLayoutChanges屬性,設(shè)置該屬性,可以添加ViewGroup增加view的過渡效果:

Android動畫機制全解析

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/ll"android:layout_width="match_parent"android:layout_height="match_parent"android:animateLayoutChanges="true"android:orientation="vertical" ><Buttonandroid:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="add"android:text="Add Button" /></LinearLayout>LayoutAnimation動畫

通過設(shè)置LayoutAnimation也同樣可以實現(xiàn)布局動畫效果,實例如下:

Android動畫機制全解析

package com.example.animtest;import android.app.Activity;import android.os.Bundle;import android.view.animation.LayoutAnimationController;import android.view.animation.ScaleAnimation;import android.widget.LinearLayout;public class AnimateLayoutAnimation extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.animate_layout_animation);LinearLayout ll = (LinearLayout) findViewById(R.id.ll);ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);sa.setDuration(2000);// 第二個參數(shù)dely : the delay by which each child's animation must be offsetLayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F);// 設(shè)置顯示的順序 這個必須要在dely不為0的時候才有效lac.setOrder(LayoutAnimationController.ORDER_NORMAL);ll.setLayoutAnimation(lac);}} View的animate方法

3.0后android對View也提供了直接作用的動畫API:

view.animate().alpha(0).y(100).setDuration(1000).withStartAction(new Runnable() {@Overridepublic void run() {}}).withEndAction(new Runnable() {@Overridepublic void run() {runOnUiThread(new Runnable() {@Overridepublic void run() {}});}}).start(); Interpolators(插值器)

插值器和估值器,是實現(xiàn)非線性動畫的基礎(chǔ),了解這些東西,才能作出不一樣的動畫效果。所謂的插值器,就是通過一些數(shù)學(xué)物理公式,計算出一些數(shù)值,提供給動畫來使用。就好比我們定義了起始值是0,結(jié)束值是100,但是這0到100具體是怎么變化的呢,這就是插值器產(chǎn)生的結(jié)果,線性的,就是勻速增長,加速的,就是按加速度增長。這些增加的算法公式,已經(jīng)不需要我們來自己設(shè)計了,Android內(nèi)置了7種插值器,基本可以滿足需求,當(dāng)然你也可以自定新的插值器。

AccelerateInterpolator 加速

Decelerate 減速

AccelerateDecelerateInterpolator 開始,和結(jié)尾都很慢,但是,中間加速

AnticipateInterpolator 開始向后一點,然后,往前拋

OvershootInterpolator 往前拋超過一點,然后返回來

AnticipateOvershootInterpolator 開始向后一點,往前拋過點,然后返回來

BounceInterpolator 結(jié)束的時候彈一下

LinearInterpolator 默認 勻速

 TypeEvalutors (估值器)

根據(jù)屬性的開始、結(jié)束值與TimeInterpolation計算出的因子計算出當(dāng)前時間的屬性值,android提供了以下幾個evalutor:

IntEvaluator:屬性的值類型為int;

FloatEvaluator:屬性的值類型為float;

ArgbEvaluator:屬性的值類型為十六進制顏色值;

TypeEvaluator:一個接口,可以通過實現(xiàn)該接口自定義Evaluator。

自定義TypeEvalutor很簡單,只需要實現(xiàn)一個方法,如FloatEvalutor的定義:

public class FloatEvaluator implements TypeEvaluator {public Object evaluate(float fraction, Object startValue,Object endValue) {float startFloat = ((Number) startValue).floatValue();return startFloat + fraction* (((Number) endValue).floatValue() - startFloat);}}

根據(jù)動畫執(zhí)行的時間跟應(yīng)用的Interplator,會計算出一個0~1之間的因子,即evalute函數(shù)中的fraction參數(shù)。

 KeyFrame

keyFrame是一個 時間/值 對,通過它可以定義一個在特定時間的特定狀態(tài),即關(guān)鍵幀,而且在兩個keyFrame之間可以定義不同的Interpolator,就好像多個動畫的拼接,第一個動畫的結(jié)束點是第二個動畫的開始點。KeyFrame是抽象類,要通過ofInt(),ofFloat(),ofObject()獲得適當(dāng)?shù)腒eyFrame,然后通過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 rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn2, pvhRotation);rotationAnim.setDuration(2000);

上述代碼的意思為:設(shè)置btn對象的width屬性值使其:

開始時 Width=400

動畫開始1/4時 Width=200

動畫開始1/2時 Width=400

動畫開始3/4時 Width=100

動畫結(jié)束時 Width=500

第一個參數(shù)為時間百分比,第二個參數(shù)是在第一個參數(shù)的時間時的屬性值。

定義了一些Keyframe后,通過PropertyValuesHolder類的方法ofKeyframe一個PropertyValuesHolder對象,然后通過ObjectAnimator.ofPropertyValuesHolder獲得一個Animator對象。

用下面的代碼可以實現(xiàn)同樣的效果(上述代碼時間值是線性,變化均勻):

ObjectAnimator oa=ObjectAnimator.ofInt(btn2, "width", 400,200,400,100,500);oa.setDuration(2000);oa.start();

代碼下載地址:http://download.csdn.net/detail/x359981514/7721651

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 日韩久久久久久 | 国变精品美女久久久久av爽 | 一区二区三区国产好 | 亚洲第一福利视频 | 欧美亚洲一区二区三区 | 精品久久久久久亚洲精品 | 91精品国产综合久久久久久丝袜 | 91看片| 国产乱码精品一区二区三区av | 密色视频 | 国产精品夜夜春夜夜爽久久电影 | 91精品一区二区三区久久久久久 | 欧美,日韩,国产精品免费观看 | 中文字幕在线免费观看 | 欧美日韩成人在线 | 亚洲一区二区 | 欧美一级片 | 狠狠操网站 | 日韩第一区 | av久久| 国产伦精品一区二区三区四区视频 | 日韩欧美精品 | 国产精品视频免费看 | 欧美日韩中文字幕在线 | 国产精自产拍久久久久久 | 国产乱码精品一区二区三区忘忧草 | 一区二区三区国产在线观看 | 国产精品一区二区三区四区 | 黄理论视频 | 亚洲精品一区二区三区中文字幕 | 成人在线视频免费观看 | 久久亚洲一区 | 男女黄色免费网站 | 亚洲一区中文 | 欧美一区第一页 | 久久精品网| 国内精品国产成人国产三级粉色 | 国产精品99久久 | 久久欧美精品一区 | 色婷婷激情 | 国产精品99久久久久久久久久久久 | 日韩在线播放视频 | 国产三级视频 | 欧美日韩视频在线观看一区 | 成年人网站在线免费看 | 亚洲一区在线日韩在线深爱 | 操人网址| 一区二区三区视频播放 | 欧美日韩免费 | 日韩一区二区在线观看 | 国产欧美精品在线 | 色综合天天综合网国产成人网 | 日本不卡高字幕在线2019 | 国产丝袜人妖ts黄檬 | 粉嫩av网站| 久久伊人草 | 日韩91视频 | 精品中文字幕在线 | 亚洲精品一区在线观看 | 午夜精品久久久久久99热软件 | 国产日韩视频 | 国产成人亚洲综合 | 欧美日韩成人 | 国产成人在线一区二区 | 中文字幕在线观看2021 | 91精品一区二区三区久久久久久 | 亚洲国产天堂久久综合 | 天堂网色 | 黄色网址大全在线观看 | 欧美一级片在线 | 久久99这里只有精品 | 亚洲精选一区二区 | av网站免费 | 狠狠色狠狠色合久久伊人 | h视频在线免费观看 | 色135综合网 | 天堂在线视频 | 国产伦精品一区二区三区四区视频 | 午夜tv免费观看 | 欧美在线观看一区 | 亚洲成人精品视频 | 久久高清 | 亚洲第一视频网站 | 国产精品一二三区 | 午夜精品久久久久久久星辰影院 | 日本福利网站 | 亚洲精品三级 | 亚洲美女在线视频 | 久久大 | 伊人www| 97国产在线视频 | 久久国产高清 | 夜本色| 欧美精品一区在线发布 | 午夜精品久久久久久久久 | 香蕉大人久久国产成人av | 亚洲特级 | 日韩精品视频在线观看免费 | 亚洲aⅴ| 欧美黄色一级 | 成人免费视频网 | 久久久久久国产精品mv | 国产免费高清 | 在线观看国产精品一区 | 成人小视频在线观看 | 国产麻豆乱码精品一区二区三区 | 久久精品免费观看 | 欧美激情高清 | 精品亚洲一区二区三区在线观看 | 夜夜视频| 成人日批| 毛片一级片 | 久久精品a一级国产免视看成人 | 一级色网站 | 不卡视频一二三区 | 天天操天天摸天天干 | 在线播放国产一区二区三区 | 正在播放国产精品 | 91天堂在线观看 | 国产免费一区二区三区 | 亚洲高清视频在线观看 | 久久一区| 久久99精品久久久久子伦 | 国产欧美精品 | 一本色道久久综合狠狠躁篇的优点 | 九九热精品视频 | 日韩欧美h | 中文字幕在线看 | 国产成人综合视频 | 中文字幕一区二区三区乱码在线 | 久久99视频 | 亚洲午夜在线 | 欧美xxxx在线 | 麻豆精品一区二区 | 国产高清美女一级a毛片久久 | 欧美日韩专区 | 成人在线 | 国产超碰人人模人人爽人人添 | 久久成人国产 | 美女张开腿视频网站免费 | 在线免费观看日韩视频 | 黄色片网站 | 久久精品国产一区二区电影 | 成人久久久精品国产乱码一区二区 | 国产精品一区二区三区在线 | 精品视频在线免费 | 欧美日韩伊人 | www.久久99| 午夜精品一区二区三区在线视频 | 美女久久久| 亚洲国产精品一区二区久久 | 久久久久中文字幕 | 亚洲视频 欧美视频 | www欧美 | 欧美日韩二区三区 | 久久综合一区二区三区 | 欧美 日韩 亚洲 一区 | 久久一日本道色综合久久 | 丁香五月网久久综合 | 日日综合 | 狠狠视频 | 日韩国产在线 | 久久久天天 | 亚洲一区二区黄 | av黄色一级 | 国产精品三级在线 | 国产免费自拍av | 欧美一级在线视频 | 亚洲免费精品网站 | 亚洲欧洲日韩 | 天天射影院 | 97免费在线视频 | 91精品国产综合久久久久久蜜臀 | 久久一区二区三区四区 | 精品中文字幕在线 | 亚洲毛片| 天堂资源最新在线 | 亚洲电影在线 | 特黄av| 欧美激情亚洲 | 国精产品一区二区三区黑人免费看 | 中文字幕在线免费 | 国产精品天堂 | 国产成人欧美一区二区三区的 | 91在线资源 | 久久久久久一区二区 | 欧美一区二区三区免费视频 | 中国大陆高清aⅴ毛片 | 国产精品爱久久久久久久 | 国产午夜精品在线 | 欧美日韩亚洲一区 | 一区二区三区四区久久 | 日日夜夜精品网站 | 亚洲色图综合 | 超碰天堂 | 成人黄色一区 | 欧美一区二区激情三区 | 久久伊人久久 | 中文乱码一区 | 国产福利在线观看视频 | 性视频一区二区 | 欧美日韩伊人 | 可以免费看黄视频的网站 | 在线观看午夜免费视频 | 91影院在线观看 | 日韩中文在线 | 鲁一鲁综合 | 亚洲天堂一区 | 国产精品丝袜视频 | 国产精品久久久久久久久免费桃花 | 国产精品www| 久久久精品网站 | 久久久久国产精品 | 日韩成人在线观看 | 九色精品 | 久久久久一区二区 | 精品国产一区二区三区久久影院 | 日韩精品一二三 | 天堂一区 | 精品一区二区三区四区五区 | 亚洲精品国产精品国自产 | 国产亚洲精品久久久久久青梅 | 欧美一区二区三区视频 | 国产女人爽到高潮免费视频 | 精品一区二区久久 | 在线观看毛片视频 | 亚洲一区二区国产 | 不卡免费在线视频 | 免费观看亚洲 | 一区二区精品 | 欧美视频在线播放 | 久久久激情视频 | 国产成人av一区二区三区 | 在线色网站 | 精品国产一区二区三区免费 | 国产一区二区三区精品久久久 | h在线看 | 日韩中文字幕在线观看 | 嫩草视频在线观看免费 | 中文字幕视频在线观看 | 国产91黄色| 日韩天堂 | 刘亦菲的毛片 | 精品国产乱码久久久久久丨区2区 | 久久久久久久久久穴 | 男女全黄一级一级高潮免费看 | 国产一区二区精品 | www.国产91| 国产亚洲成av人片在线观看桃 | 欧美日本韩国一区二区三区 | 日韩在线视频中文字幕 | 一区二区三区在线免费 | 久久久久香蕉视频 | 国产网站在线 | 极品久久 | 九九久久精品视频 | 91久久精品久久国产性色也91 | 久久综合一区二区 | 精品国产精品三级精品av网址 | 免费av大全 | 男女羞羞视频免费观看 | 国产日产精品一区二区三区四区 | 人成亚洲 | av在线一区二区三区 | 亚洲日韩欧美一区二区在线 | 欧美与黑人午夜性猛交久久久 | 精品亚洲一区二区三区四区五区 | 国产欧美精品一区二区三区 | 久久精品国产一区二区三区不卡 | www.成人在线视频 | 欧美一区二区三区电影 | 在线成人一区 | 国产精品久久久久久一级毛片 | 日韩性xxx | 成人在线播放器 | 日韩一级二级三级 | 国产一区 | 精品一区二区三区免费 | 精品一区二区免费视频 | 91精品国产欧美一区二区成人 | 国产一区二区视频在线观看 | 成人免费一区二区三区视频网站 | 中文字幕在线精品 | 日本一区二区高清视频 | 国产精品久久国产精品 | 国产精品网站在线观看 | 久久精品国产99国产 | 欧美日韩成人在线 | www国产亚洲精品 | 日韩在线观看 | 色久天堂 | 亚洲视频观看 | 欧美福利专区 | 热久久久 | 激情五月综合 | 99国产精品久久久久久久 | 天堂视频在线 | www.亚洲一区 | 久久99精品视频 | 无码少妇一区二区三区 | 一区二区三区视频免费在线观看 | 高清av网站| 九色在线观看 | 成人久久久久久久 | 国产九九九 | 日韩aⅴ一区二区三区 | 亚洲伦理影院 | av国产精品 | 一区二区免费在线观看 | 亚洲精品成人av | zzzwww在线观看免 | 日韩成人在线视频 | 日韩欧美久久 | 天堂av2020| 不卡一区二区三区四区 | 久久久片| 一级免费视频 | 精品国产三级a在线观看 | 久久中文字幕一区二区 | 国产精精品 | 日韩成人在线免费视频 | 欧美日韩国产精品久久久久 | 日日撸 | 欧美在线视频一区二区 | 日本天堂一区二区 | 国产一区二区精品 | 得得啪在线视频 | 久久a毛片| 国产精品一区二区av | 欧美精品被| www.久久久 | 午夜精品视频在线观看 | 日韩性精品 | 成人午夜视频在线观看 | 久久综合热 | 91精品国产综合久久香蕉922 | 草草视频网站 | 亚洲精品视频一区 | 亚洲视频一区二区三区 | 欧美午夜一区二区三区免费大片 | 成人国产精品久久久 | 国产精品久久久久无码av | 国产精品国色综合久久 | 欧美日韩视频 | 日韩爱爱网址 | 91精品一区二区三区久久久久久 | 羞羞av在线| 欧美一级毛片久久99精品蜜桃 | 卡通动漫第一页 | 欧美日韩一级二级三级 | 99久久精品一区二区成人 | 久色成人| 午夜精品福利在线观看 | 欧美激情一区二区 | 一级毛片av | 伊人色综合网 | av在线综合网 | 中文字幕精品一区二区三区精品 | 精品国产一区二区国模嫣然 | 爱草在线 | 欧美在线视频一区 | 精品国产一区二区三区性色 | 精品一区二区三区视频 | 亚洲一区二区三区视频 | 欧美国产精品一区二区 | 国产精品久久久久久久久免费 | 亚洲日本精品视频 | 成人国产精品视频 | 国产xxxxxxxxxx| 亚洲欧美一区二区在线观看 | 亚洲午夜精品一区二区三区 | 中文字幕自拍偷拍 | 91视频网址| 精品1区| 精品久久久久久久 | 国产精品久久精品 | 91免费版在线观看 | 91免费版在线看 | 国产精品久久久久久久久久久久久久 | 国产成人一区二区 | 日韩手机在线 | 蜜桃av人人夜夜澡人人爽 | 日韩欧美中文在线 | 久久骚 | 国产精品久久久久久久久免费桃花 | 亚洲人人艹| 人人玩人人添人人澡97 | 国产中文字幕在线 | 亚洲第一区在线 | 欧美一区二区免费 | 狠狠的干 | 不用播放器的av | 国产精品a久久久久 | 精品一区二区三区免费毛片 | 久久久久国产精品午夜一区 | 欧美国产免费 | 亚洲午夜电影 | 特黄级国产片 | 国产激情在线观看 | 一道本一二三区 | 欧美精品一二三区 | 亚洲成人精品在线观看 | 国产在线不卡视频 | 免费观看黄色一级大片 | 日韩精品一区在线 | 国产区久久 | 国产精品美女久久久久久久久久久 | 99爱免费视频 | 国产乱码精品一区二区三区中文 | 亚洲国产一区二区在线观看 | 欧美激情视频一区二区三区在线播放 | 成人午夜电影在线 | 精品久久久久久久 | 欧美日韩一级在线观看 | 色精品视频 | 男女啪啪免费网站 | 中文字幕av一区 | 九九福利| 东京久久久| 91在线视频在线 | 欧美日韩国产精品一区 | 蕉伊人| 91视频一区二区三区 | 日本大人吃奶视频xxxx | 亚洲国产精品久久久 | 国产免费黄色 | 国产综合亚洲精品一区二 | 在线观看av片 | 日韩欧美一级精品久久 | 四虎永久网址 | av中文字幕在线播放 | 一本色道精品久久一区二区三区 | 精品国产一区探花在线观看 | 日日干天天操 | 国产艳妇av视国产精选av一区 | 日韩在线中出 | 91久久| 成人欧美一区二区三区在线播放 | 欧美视频区 | 久久蜜桃精品一区二区三区综合网 | 国产精品视频一二三 | 一区二区三区在线播放 | 羞羞视频免费观看入口 | 理伦影院| 久久久久久av| 暖暖成人免费视频 | 国产精品视频导航 | 国产一区二区视频在线观看 | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 日本综合久久 | 亚洲热在线观看 | 成人国产精品久久 | 黄色小视频在线观看 | www日批 | 日韩在线精品视频 | 久久a毛片 | 日韩综合区 | 免费福利视频一区 | 欧美日韩亚洲一区 | 国内精品在线视频 | 久久久久中文字幕 | 国产欧美一二三区在线粉嫩 | 久久久高清 | 99pao成人国产永久免费视频 | 一级毛片免费看 | 国产在线观看一区 | 国产精品亚洲成在人线 | 久久久资源| 在线免费国产 | 日韩精品一区二区三区四区视频 | 成人黄色在线视频 | 亚洲不卡免费视频 | 日韩二区精品 | 久草综合网 | 狠狠色综合久久丁香婷婷 | 91麻豆精品国产91久久久资源速度 | 日韩在线观看 | 97碰碰碰免费公开在线视频 | 亚洲久久久 | 亚洲免费在线观看 | 欧美午夜一区二区福利视频 | 欧美一二三四成人免费视频 | 日韩视频一区二区 | 午夜草逼 | 欧美视频区 | 91国内精品久久 | 久久国产精品久久 | 国产成人免费视频网站视频社区 | 亚洲精品国产精品国自产 | 国产成人精品综合 | 亚洲一区二区视频 | 99精品久久久久 | 日本黄网站在线观看 | 国产一区二区成人 | 男人久久天堂 | 国产一级免费在线 | 综合色婷婷一区二区亚洲欧美国产 | 国产在线精品一区二区 | 亚洲成人三区 | 涩涩999 | 久久影院国产 | 亚洲www啪成人一区二区 | 一区二区三区四区免费观看 | 在线中文字幕av | 国产一区久久久 | 国产三级在线观看 | 国偷自产一区二区免费视频 | 在线视频二区 | 在线亚洲精品 | 在线观看视频一区二区三区 | 97精品超碰一区二区三区 | 毛片国产 | www.欧美| 国产成人99久久亚洲综合精品 | 久久久久久久99精品免费观看 | 成人影院av | 午夜久久| av国产精品| 日韩三级av在线 | 国产精品污www在线观看 | 杨门女将寡妇一级裸片看 | 精品欧美乱码久久久久久1区2区 | 国产成人精品一区二区三区在线 | 欧美一二区 | 国产成人精品一区二区三区视频 | 国产乱淫av片 | 欧美性一级 | 91hd精品少妇 | 亚洲视频一区二区三区 | 亚洲国产精品人人爽夜夜爽 | 亚洲人成在线观看 | 龙珠z国语291集普通话 | 91.成人天堂一区 | 欧美啪啪| 成人爽a毛片一区二区免费 美女高潮久久久 | 欧美自拍网站 | 国产成人精品一区二区三区视频 | 国产小视频在线播放 | 欧美成人精品一区二区男人看 | 成年视频在线观看福利资源 | 少妇精品久久久久久久久久 | 日韩成人在线视频 | 97久久精品人人做人人爽50路 | 国产一级免费视频 | 欧美99| 操人网 | 一区二区三区国产视频 | 国产精品99久久久久久宅男 | 久久网页| 欧美黑人一级爽快片淫片高清 | 亚洲一区二区三 | 免费v片| 99精品久久 | 少妇一级淫免费放 | 国产精品一区电影 | 香蕉三级 | 精品在线一区二区三区 | 视频在线一区 | 精品一区二区久久久久久久网站 | 日韩精品专区在线影院重磅 | 美女黄网 | 亚洲不卡| 综合久久综合久久 | 欧美日韩视频第一页 | 91精品久久久久久久久久 | 国产精品视频999 | av大片| 蜜臀91精品国产高清在线观看 | 日韩和的一区二区 | 精品国产乱码久久久久久88av | 妹子干综合 | 一级片网| 91亚洲国产成人久久精品网站 | 在线看国产 | 亚洲精品在线播放 | 国产精品a免费一区久久电影 | 在线视频一区二区三区 | 国产精品1区2区3区 中文字幕一区二区三区四区 | 伊人春色网 | 日韩精品在线视频观看 | 午夜影院在线 | 国产精品美女视频 | 欧美一区二区久久 | 久久亚洲一区 | √新版天堂资源在线资源 | 久久久久久久久久久久久久久久久久久 | 奇米色777欧美一区二区 | 久久伊人精品网 | www,四虎| 少妇久久久久 | 久久久久久综合 | 超碰在线91 | 亚洲日韩欧美一区二区在线 | 国语精品久久 | 日本三级黄色录像 | 国产精品久久久久精 | 在线成人一区 | avhd101在线成人播放 | 黄色毛片在线看 | 伊人青青草 | 久久久久久国产精品久久 | 欧美一级片毛片免费观看视频 | 精品久久99 | 亚洲国产高清视频 | 久久国产一区二区 | 久精品视频 | 91久久久久久久久久久久久久 | 91亚洲国产精品 | 国产免费看 | 亚洲成人一区二区三区 | 一二三四在线视频观看社区 | 在线视频 欧美日韩 | 91精品国产一区二区 | 精品国产一区二区三区性色 | 九九热精|