欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android屬性動(dòng)畫(huà)之ValueAnimator代碼詳解

 更新時(shí)間:2018年02月02日 10:37:25   作者:Mirhunana  
這篇文章主要介紹了Android屬性動(dòng)畫(huà)之ValueAnimator代碼詳解,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下

屬性動(dòng)畫(huà)通過(guò)改變一個(gè)對(duì)象的屬性值來(lái)進(jìn)行動(dòng)畫(huà),屬性動(dòng)畫(huà)包含了以下幾個(gè)特性:

1、持續(xù)時(shí)間(Duration)

主要用來(lái)定義動(dòng)畫(huà)的持續(xù)時(shí)間,默認(rèn)值為300ms。

2、時(shí)間插值器(Time interpolation)

指定時(shí)間變化的百分比,就是當(dāng)前流逝時(shí)間除以指定的持續(xù)時(shí)間,這個(gè)可以自定義,繼承Interpolator,重寫(xiě)getInterpolation方法。

3、重復(fù)次數(shù)和行為(Repeat count and behavior)

指定動(dòng)畫(huà)的執(zhí)行次數(shù)和動(dòng)畫(huà)的重復(fù)模式

4、動(dòng)畫(huà)集(Animator sets)

可以把多個(gè)動(dòng)畫(huà)放到一個(gè)集合中,是他們同時(shí)執(zhí)行,或者指定它們直接的順序和延遲。

5、Frame refresh delay(幀刷新延遲)

可以指定如何去刷新動(dòng)畫(huà)的幀,默認(rèn)是每10ms刷新一次,這個(gè)刷新也取決于系統(tǒng)的繁忙程度。

上面我們知道屬性動(dòng)畫(huà)就是改變對(duì)象的屬性值來(lái)實(shí)現(xiàn)動(dòng)畫(huà),ValueAnimator的特點(diǎn)就是你不需要明確的指定你要改變的對(duì)象和屬性,你只需要得到一個(gè)動(dòng)態(tài)的值來(lái)自己去設(shè)置相應(yīng)對(duì)象的屬性,也就是它就是提供屬性的變化值,你拿到這個(gè)值可以動(dòng)態(tài)的更改對(duì)象屬性值??偨Y(jié)一句就是監(jiān)聽(tīng)動(dòng)畫(huà)過(guò)程,自己實(shí)現(xiàn)屬性的改變。

舉個(gè)例子:

// 這里指定了值的變化范圍
ValueAnimator animator = ValueAnimator.ofFloat(0, 500);
// 這里指定變化持續(xù)時(shí)間
animator.setDuration(1000);
//開(kāi)始動(dòng)畫(huà)
animator.start()
//開(kāi)始動(dòng)畫(huà)后,我們可以動(dòng)態(tài)的獲取變化值
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
  @Override
  public void onAnimationUpdate(ValueAnimator animation)
  {
    //根據(jù)變化值來(lái)設(shè)置imageView對(duì)象的Y軸坐標(biāo),這樣就實(shí)現(xiàn)了imageView的垂直移動(dòng)
    imageView.setTranslationY((Float) animation.getAnimatedValue());
  }
});

上面使用imageView.setTranslationY((Float) animation.getAnimatedValue())來(lái)動(dòng)態(tài)的改變圖片的translationY屬性,需要說(shuō)明的是,如果在低版本中,我們使用的是NineOldAnimations這個(gè)庫(kù),用法跟系統(tǒng)基本一致,在NineOldAnimations里面我們動(dòng)態(tài)改變對(duì)象的屬性的時(shí)候,它提供了一個(gè)ViewHelper類(lèi),它是設(shè)置各種動(dòng)畫(huà)值的幫助類(lèi),可以簡(jiǎn)單的設(shè)置并應(yīng)用動(dòng)畫(huà)值。所以在3.0以下版本中,使用ViewHelper來(lái)進(jìn)行屬性值的改變,上面的設(shè)置等同如下:

ViewHelper.setTranslationX(imageView, (Float) animation.getAnimatedValue());

上面的過(guò)程如下圖所示:

上面的過(guò)程應(yīng)該比較清晰,在上面我們就設(shè)置了一個(gè)持續(xù)時(shí)間,下面我們可以來(lái)看看我們可以為ValueAnimator設(shè)置其他哪些東西。

public ObjectAnimator setDuration(long duration)
設(shè)置持續(xù)時(shí)間

public void setEvaluator(TypeEvaluator value)
設(shè)置估值器

public void setInterpolator(/*Time*/Interpolator value)
設(shè)置插值器

public void setTarget(Object target)
設(shè)置目標(biāo)對(duì)象

public void setRepeatCount(int value)
設(shè)置動(dòng)畫(huà)重復(fù)次數(shù)

public void setRepeatMode(int value)
設(shè)置重復(fù)模式

public void setValues(PropertyValuesHolder... values)
設(shè)置值

public void setStartDelay(long startDelay)
設(shè)置啟動(dòng)延時(shí)

public static void setFrameDelay(long frameDelay)
設(shè)置幀延遲

public void setIntValues(int... values)
設(shè)置Int值,對(duì)應(yīng)ValueAnimator.ofInt函數(shù)

public void setFloatValues(float... values)
設(shè)置Float值。對(duì)應(yīng)ValueAnimator.ofFloat函數(shù)

public void setCurrentPlayTime(long playTime)
設(shè)置當(dāng)前執(zhí)行時(shí)間

public void setObjectValues(Object... values)
設(shè)置Object值,對(duì)應(yīng)ValueAnimator.ofObject函數(shù)

上面我們知道ValueAnimator是主要提供一個(gè)動(dòng)態(tài)的變化值,這個(gè)值是怎么來(lái)變化的,它的變化函數(shù)就是由估值器和插值器來(lái)決定的,我們可以自定義估值器和插值器來(lái)自定義值的變化,另外這個(gè)變化值的類(lèi)型,ValueAnimator提供了四種類(lèi)型,Int,F(xiàn)loat,Objcet,PropertyValuesHolder,它囊括了所有的類(lèi)型。

1、變化值的類(lèi)型的確定

我們知道,在我們定義一個(gè)屬性動(dòng)畫(huà)對(duì)象的時(shí)候,可以不需要通過(guò)自己來(lái)創(chuàng)建的,主要有四種方式:

public static ValueAnimator ofInt(int... values) 

public static ValueAnimator ofFloat(int... values)

public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) 

public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)

從上面我們可以看到,不同的方式其實(shí)對(duì)應(yīng)的就是不同類(lèi)型的變化值。第一種方式的變化值類(lèi)型為Int,第二種方式的變化值類(lèi)型為Float,第三種方式的變化值類(lèi)型為Object,第四種方式的變化值類(lèi)型為PropertyValuesHolder,它其實(shí)是一個(gè)集合。

2、估值器和插值器

對(duì)于給定一個(gè)范圍的值,例如上面例子中ValueAnimator.ofFloat(0, 500),它給定的變化范圍為[0, 500],那么在這個(gè)范圍內(nèi)到底是如何變化的呢?可以是線性變化,可以是加速變化,可以是減速變化,在內(nèi)部已經(jīng)為我們定義好了幾種變化方式,我們可以根據(jù)情況來(lái)進(jìn)行使用。

首先我們來(lái)說(shuō)說(shuō)時(shí)間插值器和類(lèi)型估值器

TimeInterpolator中文翻譯為時(shí)間插值器,它的作用是根據(jù)時(shí)間流逝的百分比來(lái)計(jì)算出當(dāng)前屬性值改變的百分比,系統(tǒng)預(yù)置的有LinearInterpolator(線性插值器:勻速動(dòng)畫(huà))、AccelerateDecelerateInterpolator(加速減速插值器:動(dòng)畫(huà)兩頭慢中間快)和DecelerateInterpolator(減速插值器:動(dòng)畫(huà)越來(lái)越慢)等;

下面看看線性插值器的源碼:

public class LinearInterpolator implements Interpolator {
	public LinearInterpolator() {
	}
	public LinearInterpolator(Context context, AttributeSet attrs) {
	}
	public float getInterpolation(float input) {
		return input;
	}
}

我們自定義插值器的時(shí)候,只需要重寫(xiě)getInterpolation方法,其中傳入的input參數(shù)就是時(shí)間流逝的百分比,這個(gè)百分比就是當(dāng)前時(shí)間的流逝除以設(shè)置的持續(xù)時(shí)間Duration來(lái)得到的。我們實(shí)現(xiàn)這個(gè)函數(shù)的時(shí)候,可以通過(guò)改變這個(gè)值來(lái)實(shí)現(xiàn)我們想要的效果。

TypeEvaluator的中文翻譯為類(lèi)型估值算法,它的作用是根據(jù)當(dāng)前屬性改變的百分比來(lái)計(jì)算改變后的屬性值,系統(tǒng)預(yù)置的有IntEvaluator(針對(duì)整型屬性)、FloatEvaluator(針對(duì)浮點(diǎn)型屬性)和ArgbEvaluator(針對(duì)Color屬性)。

我們知道插值器的作用就是返回當(dāng)前屬性改變的百分比,這個(gè)百分比我們可以通過(guò)重寫(xiě)getInterpolation來(lái)自定義。其實(shí)真正的變化后的值是從估值器來(lái)得到的。

我們來(lái)看看IntEvaluator的源碼:

public class IntEvaluator implements TypeEvaluator<Integer> { 

  public Integer evaluate(float fraction, Integer startValue, Integer endValue) { 
    int startInt = startValue; 
    return (int)(startInt + fraction * (endValue - startInt)); 
  } 
} 

上述算法很簡(jiǎn)單,evaluate的三個(gè)參數(shù)分別表示:估值小數(shù)、開(kāi)始值和結(jié)束值,其中的估值小數(shù)就是上面getInterpolation的返回值,開(kāi)始值就是變化值的開(kāi)始,結(jié)束值就是變化值的結(jié)束,對(duì)應(yīng)上面例子ValueAnimator.ofFloat(0, 500),開(kāi)始值為0,結(jié)束值為500,通過(guò)這三個(gè)參數(shù),最終計(jì)算出變化后的值,然后將這個(gè)值返回去,我們最終得到的就是這個(gè)值,然后對(duì)指定對(duì)象的屬性進(jìn)行設(shè)置,這樣來(lái)實(shí)現(xiàn)指定屬性值的變化,從而實(shí)現(xiàn)了動(dòng)畫(huà)效果。

所以我們?nèi)绻M远x變化值的變化快慢,我們需要自定義一個(gè)插值器和一個(gè)估值器,插值器是為估值器服務(wù)的,估值器是為我們服務(wù)的,因?yàn)樗罱K返回了變化后的值。

最后,我們?nèi)绾蔚玫竭@個(gè)變化后的值呢?從上面的例子中我們可以看到,我們只需要使用ValueAnimator的addUpdateListener函數(shù)來(lái)增加一個(gè)更新監(jiān)聽(tīng),當(dāng)這個(gè)值變化之后,就會(huì)回調(diào)onAnimationUpdate函數(shù),在傳入的參數(shù)ValueAnimator對(duì)象中使用getAnimatedValue函數(shù)我們就可以獲取到變化后的那個(gè)值,拿到這個(gè)變化后的值之后我們就可以動(dòng)態(tài)的更新對(duì)象的屬性值了。

還有需要注意的是,我們?nèi)绻麤](méi)有顯式指定插值器和估值器,它內(nèi)部有默認(rèn)值。

下面我們來(lái)舉個(gè)例子;

/** 
 * 拋物線 
 * @param view 
 */ 
public void paowuxian(View view) 
{ 

  ValueAnimator valueAnimator = new ValueAnimator(); 
  valueAnimator.setDuration(3000); 
  //這個(gè)地方設(shè)置了變化值的類(lèi)型
  valueAnimator.setObjectValues(new PointF(0, 0)); 
  //設(shè)置插值器
  valueAnimator.setInterpolator(new LinearInterpolator()); 
  //設(shè)置估值器
  valueAnimator.setEvaluator(new TypeEvaluator<PointF>() 
  { 
    // fraction = t / duration 
    @Override 
    public PointF evaluate(float fraction, PointF startValue, 
        PointF endValue) 
    { 
      Log.e(TAG, fraction * 3 + ""); 
      // x方向200px/s ,則y方向0.5 * 10 * t 
      PointF point = new PointF(); 
      point.x = 200 * fraction * 3; 
      point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3); 
      //返回變化值
      //這個(gè)返回值會(huì)在addUpdateListener的回調(diào)中得到
      return point; 
    } 
  }); 

  valueAnimator.start(); 
  valueAnimator.addUpdateListener(new AnimatorUpdateListener() 
  { 
    @Override 
    public void onAnimationUpdate(ValueAnimator animation) 
    { 
      // 得到估值器里面的那個(gè)返回值
      PointF point = (PointF) animation.getAnimatedValue();
      //設(shè)置屬性值 
      mBlueBall.setX(point.x); 
      mBlueBall.setY(point.y); 

    } 
  }); 
} 

上面基本說(shuō)清楚了ValueAnimator的特定和用法,下面來(lái)說(shuō)說(shuō)如何為這個(gè)動(dòng)畫(huà)添加事件監(jiān)聽(tīng)。

ValueAnimator animator = ValueAnimator.ofFloat();
animator.setFloatValues(0, 500);
animator.setTarget(imageView);
animator.setDuration(1000);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
  @Override
  public void onAnimationUpdate(ValueAnimator animation)
  {
    imageView.setTranslationY((Float) animation.getAnimatedValue());
  }
});

animator.addListener(new Animator.AnimatorListener(){

  @Override
  public void onAnimationStart(Animator animation) {
    Log.d(TAG, "onAnimationStart");
  }

  @Override
  public void onAnimationEnd(Animator animation) {
    Log.d(TAG, "onAnimationEnd");
  }

  @Override
  public void onAnimationCancel(Animator animation) {
    Log.d(TAG, "onAnimationCancel");
  }

  @Override
  public void onAnimationRepeat(Animator animation) {
    Log.d(TAG, "onAnimationRepeat");
  }
});

從上面可以看到直接添加一個(gè)監(jiān)聽(tīng)就可以了,這樣就可以監(jiān)聽(tīng)動(dòng)畫(huà)的開(kāi)始、結(jié)束、被取消、重復(fù)等事件,上面你需要重寫(xiě)上面四個(gè)函數(shù)一個(gè)都不能少,如果你只需要重寫(xiě)自己需要的函數(shù),那你可以使用AnimatorListenerAdapter,例如只需要重新onAnimationEnd函數(shù),因?yàn)?code>AnimatorListenerAdapter繼承自AnimatorListener

總結(jié)

以上本文關(guān)于Android屬性動(dòng)畫(huà)之ValueAnimator代碼詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專(zhuān)題,如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!

相關(guān)文章

最新評(píng)論