小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Android 動(dòng)畫(huà):你真的會(huì)使用插值器與估值器嗎?(含詳細(xì)實(shí)例教學(xué))

 萬(wàn)皇之皇 2018-01-14

關(guān)鍵時(shí)刻,第一時(shí)間送達(dá)!

前言

  • 動(dòng)畫(huà)的使用 是 Android 開(kāi)發(fā)中常用的知識(shí)

  • 可是動(dòng)畫(huà)的種類(lèi)繁多、使用復(fù)雜,每當(dāng)需要 采用自定義動(dòng)畫(huà)實(shí)現(xiàn)復(fù)雜的動(dòng)畫(huà)效果時(shí),很多開(kāi)發(fā)者就顯得束手無(wú)策

  • Android中 補(bǔ)間動(dòng)畫(huà) & 屬性動(dòng)畫(huà)實(shí)現(xiàn)動(dòng)畫(huà)的原理是:

  • 其中,步驟2中的 插值器(Interpolator)和估值器(TypeEvaluator)是實(shí)現(xiàn) 復(fù)雜動(dòng)畫(huà)效果的關(guān)鍵

  • 本文主要講解 將詳細(xì)講解 插值器(Interpolator)和估值器(TypeEvaluator),通過(guò)閱讀本文你將能輕松實(shí)現(xiàn)復(fù)雜的動(dòng)畫(huà)效果。

目錄

1. 插值器(Interpolator)

1.1 簡(jiǎn)介

  • 定義:一個(gè)接口

  • 作用:設(shè)置 屬性值 從初始值過(guò)渡到結(jié)束值 的變化規(guī)律

  1. 如勻速、加速 & 減速 等等

  2. 即確定了 動(dòng)畫(huà)效果變化的模式,如勻速變化、加速變化 等等

1.2 應(yīng)用場(chǎng)景

實(shí)現(xiàn)非線性運(yùn)動(dòng)的動(dòng)畫(huà)效果

非線性運(yùn)動(dòng):動(dòng)畫(huà)改變的速率不是一成不變的,如加速 & 減速運(yùn)動(dòng)都屬于非線性運(yùn)動(dòng)

1.3 具體使用

a. 設(shè)置方式

插值器在動(dòng)畫(huà)的使用有兩種方式:在XML / Java代碼中設(shè)置:

設(shè)置方法1:在 動(dòng)畫(huà)效果的XML代碼中設(shè)置插值器屬性android:interpolator

'1.0' encoding='utf-8'?>
scale xmlns:android='http://schemas./apk/res/android'

   android:interpolator='@android:anim/overshoot_interpolator'    
   // 通過(guò)資源ID設(shè)置插值器    
   android:duration='3000'    
   android:fromXScale='0.0'    
   android:fromYScale='0.0'    
   android:pivotX='50%'    
   android:pivotY='50%'    
   android:toXScale='2'    
   android:toYScale='2' />

設(shè)置方法2:在 Java 代碼中設(shè)置

Button mButton = (Button) findViewById(R.id.Button);
       // 步驟1:創(chuàng)建 需要設(shè)置動(dòng)畫(huà)的 視圖View

Animation alphaAnimation = new AlphaAnimation(1,0);        
       // 步驟2:創(chuàng)建透明度動(dòng)畫(huà)的對(duì)象 & 設(shè)置動(dòng)畫(huà)效果

       alphaAnimation.setDuration(3000);        
       Interpolator overshootInterpolator = new OvershootInterpolator();      
        // 步驟3:創(chuàng)建對(duì)應(yīng)的插值器類(lèi)對(duì)象        
        
        alphaAnimation.setInterpolator(overshootInterpolator);        
        // 步驟4:給動(dòng)畫(huà)設(shè)置插值器        
        
        mButton.startAnimation(alphaAnimation);        
        // 步驟5:播放動(dòng)畫(huà)
  • 那么使用插值器時(shí)的資源ID是什么呢?即有哪些類(lèi)型的插值器可供我們使用呢?

  • 下面將介紹 Android內(nèi)置默認(rèn)的插值器

b. 系統(tǒng)內(nèi)置插值器類(lèi)型

  • Android內(nèi)置了 9 種內(nèi)置的插值器實(shí)現(xiàn):

使用時(shí):

  • 當(dāng)在XML文件設(shè)置插值器時(shí),只需傳入對(duì)應(yīng)的插值器資源ID即可

  • 當(dāng)在Java代碼設(shè)置插值器時(shí),只需創(chuàng)建對(duì)應(yīng)的插值器對(duì)象即可

系統(tǒng)默認(rèn)的插值器是AccelerateDecelerateInterpolator,即先加速后減速

  • 系統(tǒng)內(nèi)置插值器的效果圖:

  • 使用Android內(nèi)置的插值器能滿足大多數(shù)的動(dòng)畫(huà)需求

  • 如果上述9個(gè)插值器無(wú)法滿足需求,還可以自定義插值器

  • 下面將介紹如何自定義插值器(Interpolator)

c. 自定義插值器

  • 本質(zhì):根據(jù)動(dòng)畫(huà)的進(jìn)度(0%-100%)計(jì)算出當(dāng)前屬性值改變的百分比

  • 具體使用:自定義插值器需要實(shí)現(xiàn) Interpolator / TimeInterpolator接口 & 復(fù)寫(xiě)getInterpolation()

  1. 補(bǔ)間動(dòng)畫(huà) 實(shí)現(xiàn) Interpolator接口;屬性動(dòng)畫(huà)實(shí)現(xiàn)TimeInterpolator接口

  2. TimeInterpolator接口是屬性動(dòng)畫(huà)中新增的,用于兼容Interpolator接口,這使得所有過(guò)去的Interpolator實(shí)現(xiàn)類(lèi)都可以直接在屬性動(dòng)畫(huà)使用

// Interpolator接口
public interface Interpolator {
   
     // 內(nèi)部只有一個(gè)方法    
     float getInterpolation(float input) {    
         // 參數(shù)說(shuō)明        
         // input值值變化范圍是0-1,且隨著動(dòng)畫(huà)進(jìn)度(0% - 100% )均勻變化        
         // 即動(dòng)畫(huà)開(kāi)始時(shí),input值 = 0;動(dòng)畫(huà)結(jié)束時(shí)input = 1        
         // 而中間的值則是隨著動(dòng)畫(huà)的進(jìn)度(0% - 100%)在0到1之間均勻增加

     ...// 插值器的計(jì)算邏輯      
         
      return xxx;      
     // 返回的值就是用于估值器繼續(xù)計(jì)算的fraction值,下面會(huì)詳細(xì)說(shuō)明    }  

// TimeInterpolator接口
// 同上
public interface TimeInterpolator {
     float getInterpolation(float input);  
}

在學(xué)習(xí)自定義插值器前,我們先來(lái)看兩個(gè)已經(jīng)實(shí)現(xiàn)好的系統(tǒng)內(nèi)置差值器:

  • 勻速插值器:LinearInterpolator

  • 先加速再減速 插值器:AccelerateDecelerateInterpolator

// 勻速差值器:LinearInterpolator
@HasNativeInterpolator  
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {    

  // 僅貼出關(guān)鍵代碼  
  ...  
   public float getInterpolation(float input) {      
   
      return input;          
      // 沒(méi)有對(duì)input值進(jìn)行任何邏輯處理,直接返回        
      // 即input值 = fraction值        
      // 因?yàn)閕nput值是勻速增加的,因此fraction值也是勻速增加的,所以動(dòng)畫(huà)的運(yùn)動(dòng)情況也是勻速的,所以是勻速插值器  
   }  

// 先加速再減速 差值器:AccelerateDecelerateInterpolator
@HasNativeInterpolator  
public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {        
    // 僅貼出關(guān)鍵代碼  
 ...    
   public float getInterpolation(float input) {    
       return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;        
       // input的運(yùn)算邏輯如下:
       // 使用了余弦函數(shù),因input的取值范圍是0到1,那么cos函數(shù)中的取值范圍就是π到2π。
       // 而cos(π)的結(jié)果是-1,cos(2π)的結(jié)果是1  
       // 所以該值除以2加上0.5后,getInterpolation()方法最終返回的結(jié)果值還是在0到1之間。只不過(guò)經(jīng)過(guò)了余弦運(yùn)算之后,最終的結(jié)果不再是勻速增加的了,而是經(jīng)歷了一個(gè)先加速后減速的過(guò)程        
       // 所以最終,fraction值 = 運(yùn)算后的值 = 先加速后減速        
       // 所以該差值器是先加速再減速的    
   }      
   
   }
  • 從上面看出,自定義插值器的關(guān)鍵在于:對(duì)input值 根據(jù)動(dòng)畫(huà)的進(jìn)度(0%-100%)通過(guò)邏輯計(jì)算 計(jì)算出當(dāng)前屬性值改變的百分比

  • 下面我將用一個(gè)實(shí)例來(lái)說(shuō)明該如何自定義插值器

實(shí)例

  • 目的:寫(xiě)一個(gè)自定義Interpolator:先減速后加速

步驟1:根據(jù)需求實(shí)現(xiàn)Interpolator接口
DecelerateAccelerateInterpolator.java

/**
* Created by Carson_Ho on 17/4/19.
*/

public class DecelerateAccelerateInterpolator implements TimeInterpolator {    

   @Override    
   public float getInterpolation(float input) {    
       float result;
       if (input <=>0.5) {        
           result = (float) (Math.sin(Math.PI * input)) / 2;        
       // 使用正弦函數(shù)來(lái)實(shí)現(xiàn)先減速后加速的功能,邏輯如下:    
              // 因?yàn)檎液瘮?shù)初始弧度變化值非常大,剛好和余弦函數(shù)是相反的            
              // 隨著弧度的增加,正弦函數(shù)的變化值也會(huì)逐漸變小,這樣也就實(shí)現(xiàn)了減速的效果。            
              // 當(dāng)弧度大于π/2之后,整個(gè)過(guò)程相反了過(guò)來(lái),現(xiàn)在正弦函數(shù)的弧度變化值非常小,漸漸隨著弧度繼續(xù)增加,變化值越來(lái)越大,弧度到π時(shí)結(jié)束,這樣從0過(guò)度到π,也就實(shí)現(xiàn)了先減速后加速的效果        
       } else {      
           result = (float) (2 - Math.sin(Math.PI * input)) / 2;        
       }        
       return result;        
       // 返回的result值 = 隨著動(dòng)畫(huà)進(jìn)度呈先減速后加速的變化趨勢(shì)    
    }
 }

MainActivity.java

mButton = (Button) findViewById(R.id.Button);
        // 創(chuàng)建動(dòng)畫(huà)作用對(duì)象:此處以Button為例        
        
        float curTranslationX = mButton.getTranslationX();        
        // 獲得當(dāng)前按鈕的位置        
        
        ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, 'translationX', curTranslationX, 300,curTranslationX);        
        // 創(chuàng)建動(dòng)畫(huà)對(duì)象 & 設(shè)置動(dòng)畫(huà)        
        // 表示的是:        
        // 動(dòng)畫(huà)作用對(duì)象是mButton        
        // 動(dòng)畫(huà)作用的對(duì)象的屬性是X軸平移        
        // 動(dòng)畫(huà)效果是:從當(dāng)前位置平移到 x=1500 再平移到初始位置        
        animator.setDuration(5000);        
        animator.setInterpolator(new DecelerateAccelerateInterpolator());        
        // 設(shè)置插值器        
        animator.start();        
        // 啟動(dòng)動(dòng)畫(huà)

效果圖


2. 估值器(TypeEvaluator)

2.1 簡(jiǎn)介

  • 定義:一個(gè)接口

  • 作用:設(shè)置 屬性值 從初始值過(guò)渡到結(jié)束值 的變化具體數(shù)值

  1. 插值器(Interpolator)決定 值 的變化規(guī)律(勻速、加速blabla),即決定的是變化趨勢(shì);而接下來(lái)的具體變化數(shù)值則交給
    而估值器

  2. 屬性動(dòng)畫(huà)特有的屬性

2.2 應(yīng)用場(chǎng)景

協(xié)助插值器 實(shí)現(xiàn)非線性運(yùn)動(dòng)的動(dòng)畫(huà)效果

非線性運(yùn)動(dòng):動(dòng)畫(huà)改變的速率不是一成不變的,如加速 & 減速運(yùn)動(dòng)都屬于非線性運(yùn)動(dòng)

2.3 具體使用

a. 設(shè)置方式

ObjectAnimator anim = ObjectAnimator.ofObject(myView2, 'height', new Evaluator(),1,3);
// 在第4個(gè)參數(shù)中傳入對(duì)應(yīng)估值器類(lèi)的對(duì)象// 系統(tǒng)內(nèi)置的估值器有3個(gè):
// IntEvaluator:以整型的形式從初始值 - 結(jié)束值 進(jìn)行過(guò)渡
// FloatEvaluator:以浮點(diǎn)型的形式從初始值 - 結(jié)束值 進(jìn)行過(guò)渡
// ArgbEvaluator:以Argb類(lèi)型的形式從初始值 - 結(jié)束值 進(jìn)行過(guò)渡


  • 如果上述內(nèi)置的估值器無(wú)法滿足需求,還可以自定義估值器

  • 下面將介紹如何自定義插值器(Interpolator)

b. 自定義估值器

  • 本質(zhì):根據(jù) 插值器計(jì)算出當(dāng)前屬性值改變的百分比 & 初始值 & 結(jié)束值 來(lái)計(jì)算 當(dāng)前屬性具體的數(shù)值

如:動(dòng)畫(huà)進(jìn)行了50%(初始值=100,結(jié)束值=200 ),那么勻速插值器計(jì)算出了當(dāng)前屬性值改變的百分比是50%,那么估值器則負(fù)責(zé)計(jì)算當(dāng)前屬性值 = 100 + (200-100)x50% = 150.

  • 具體使用:自定義估值器需要實(shí)現(xiàn) TypeEvaluator接口 & 復(fù)寫(xiě)evaluate()

public interface TypeEvaluator {

   public Object evaluate(float fraction, Object startValue, Object endValue) {
 // 參數(shù)說(shuō)明// fraction:插值器getInterpolation()的返回值
 // startValue:動(dòng)畫(huà)的初始值
 // endValue:動(dòng)畫(huà)的結(jié)束值
 
       ....// 估值器的計(jì)算邏輯

       return xxx;
       // 賦給動(dòng)畫(huà)屬性的具體數(shù)值        
       // 使用反射機(jī)制改變屬性變化

// 特別注意
// 那么插值器的input值 和 估值器fraction有什么關(guān)系呢?
// 答:input的值決定了fraction的值:input值經(jīng)過(guò)計(jì)算后傳入到插值器的getInterpolation(),然后通過(guò)實(shí)現(xiàn)getInterpolation()中的邏輯算法,根據(jù)input值來(lái)計(jì)算出一個(gè)返回值,而這個(gè)返回值就是fraction了    
     }  
}

在學(xué)習(xí)自定義插值器前,我們先來(lái)看一個(gè)已經(jīng)實(shí)現(xiàn)好的系統(tǒng)內(nèi)置差值器:浮點(diǎn)型插值器:FloatEvaluator

public class FloatEvaluator implements TypeEvaluator {
 // FloatEvaluator實(shí)現(xiàn)了TypeEvaluator接口
 
 // 重寫(xiě)evaluate()

 
   public Object evaluate(float fraction, Object startValue, Object endValue) {
   // 參數(shù)說(shuō)明
  // fraction:表示動(dòng)畫(huà)完成度(根據(jù)它來(lái)計(jì)算當(dāng)前動(dòng)畫(huà)的值)
  // startValue、endValue:動(dòng)畫(huà)的初始值和結(jié)束值
       float startFloat = ((Number) startValue).floatValue();          
       
       return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);          
       // 初始值 過(guò)渡 到結(jié)束值 的算法是:        
       // 1. 用結(jié)束值減去初始值,算出它們之間的差值      
        // 2. 用上述差值乘以fraction系數(shù)        
        // 3. 再加上初始值,就得到當(dāng)前動(dòng)畫(huà)的值    
   }
}
  • 屬性動(dòng)畫(huà)中的ValueAnimator.ofInt() & ValueAnimator.ofFloat()都具備系統(tǒng)內(nèi)置的估值器,即FloatEvaluator & IntEvaluator

    即系統(tǒng)已經(jīng)默認(rèn)實(shí)現(xiàn)了 如何從初始值 過(guò)渡到 結(jié)束值 的邏輯

  • 但對(duì)于ValueAnimator.ofObject(),從上面的工作原理可以看出并沒(méi)有系統(tǒng)默認(rèn)實(shí)現(xiàn),因?yàn)閷?duì)對(duì)象的動(dòng)畫(huà)操作復(fù)雜 & 多樣,系統(tǒng)無(wú)法知道如何從初始對(duì)象過(guò)度到結(jié)束對(duì)象

  • 因此,對(duì)于ValueAnimator.ofObject(),我們需自定義估值器(TypeEvaluator)來(lái)告知系統(tǒng)如何進(jìn)行從 初始對(duì)象 過(guò)渡到 結(jié)束對(duì)象的邏輯

  • 自定義實(shí)現(xiàn)的邏輯如下

// 實(shí)現(xiàn)TypeEvaluator接口
public class ObjectEvaluator implements TypeEvaluator{

 // 復(fù)寫(xiě)evaluate()
 // 在evaluate()里寫(xiě)入對(duì)象動(dòng)畫(huà)過(guò)渡的邏輯    
 @Override      
 public Object evaluate(float fraction, Object startValue, Object endValue) {
      // 參數(shù)說(shuō)明        
      // fraction:表示動(dòng)畫(huà)完成度(根據(jù)它來(lái)計(jì)算當(dāng)前動(dòng)畫(huà)的值)        
      // startValue、endValue:動(dòng)畫(huà)的初始值和結(jié)束值

       ... // 寫(xiě)入對(duì)象動(dòng)畫(huà)過(guò)渡的邏輯

       return value;          
      // 返回對(duì)象動(dòng)畫(huà)過(guò)渡的邏輯計(jì)算后的值

   }

實(shí)例說(shuō)明

  • 下面我將用實(shí)例說(shuō)明 該如何自定義TypeEvaluator接口并通過(guò)ValueAnimator.ofObject()實(shí)現(xiàn)動(dòng)畫(huà)效果

  • 實(shí)現(xiàn)的動(dòng)畫(huà)效果:一個(gè)圓從一個(gè)點(diǎn) 移動(dòng)到 另外一個(gè)點(diǎn)

  • 工程目錄文件如下:

步驟1:定義對(duì)象類(lèi)

  • 因?yàn)閂alueAnimator.ofObject()是面向?qū)ο蟛僮鞯?,所以需要自定義對(duì)象類(lèi)。

  • 本例需要操作的對(duì)象是 圓的點(diǎn)坐標(biāo)
    Point.java

public class Point {

   // 設(shè)置兩個(gè)變量用于記錄坐標(biāo)的位置    
   private float x;    
   private float y;    
   
   // 構(gòu)造方法用于設(shè)置坐標(biāo)    
   public Point(float x, float y) {
           this.x = x;        
           this.y = y;
   }    
   
   // get方法用于獲取坐標(biāo)    
   public float getX() {
           return x;    
   }    
   
   public float getY() {        
           return y;    
   }
}

步驟2:根據(jù)需求實(shí)現(xiàn)TypeEvaluator接口

  • 實(shí)現(xiàn)TypeEvaluator接口的目的是自定義如何 從初始點(diǎn)坐標(biāo) 過(guò)渡 到結(jié)束點(diǎn)坐標(biāo);

  • 本例實(shí)現(xiàn)的是一個(gè)從左上角到右下角的坐標(biāo)過(guò)渡邏輯。

PointEvaluator.java

// 實(shí)現(xiàn)TypeEvaluator接口
public class PointEvaluator implements TypeEvaluator {
   // 復(fù)寫(xiě)evaluate()    
   // 在evaluate()里寫(xiě)入對(duì)象動(dòng)畫(huà)過(guò)渡的邏輯    
   @Override    
   public Object evaluate(float fraction, Object startValue, Object endValue) {
       // 將動(dòng)畫(huà)初始值startValue 和 動(dòng)畫(huà)結(jié)束值endValue 強(qiáng)制類(lèi)型轉(zhuǎn)換成Point對(duì)象        
       Point startPoint = (Point) startValue;        
       Point endPoint = (Point) endValue;        
       
       // 根據(jù)fraction來(lái)計(jì)算當(dāng)前動(dòng)畫(huà)的x和y的值        
       float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());        
       float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());
       
       // 將計(jì)算后的坐標(biāo)封裝到一個(gè)新的Point對(duì)象中并返回        
       Point point = new Point(x, y);        
       return point;    
   }
   
}
  • 上面步驟是根據(jù)需求自定義TypeEvaluator的實(shí)現(xiàn)

  • 下面將講解如何通過(guò)對(duì) Point 對(duì)象進(jìn)行動(dòng)畫(huà)操作,從而實(shí)現(xiàn)整個(gè)自定義View的動(dòng)畫(huà)效果。

步驟3:將屬性動(dòng)畫(huà)作用到自定義View當(dāng)中

MyView.java

/**
* Created by Carson_Ho on 17/4/18.
*/
public class MyView extends View {
   // 設(shè)置需要用到的變量    
   public static final float RADIUS = 70f;// 圓的半徑 = 70    
   private Point currentPoint;// 當(dāng)前點(diǎn)坐標(biāo)    
   private Paint mPaint;// 繪圖畫(huà)筆    
   
   // 構(gòu)造方法(初始化畫(huà)筆)    
   public MyView(Context context, AttributeSet attrs) {  
       super(context, attrs);        
       // 初始化畫(huà)筆        
       mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        
       mPaint.setColor(Color.BLUE);    
   }    
       
   // 復(fù)寫(xiě)onDraw()從而實(shí)現(xiàn)繪制邏輯    
   // 繪制邏輯:先在初始點(diǎn)畫(huà)圓,通過(guò)監(jiān)聽(tīng)當(dāng)前坐標(biāo)值(currentPoint)的變化,每次變化都調(diào)用onDraw()重新繪制圓,從而實(shí)現(xiàn)圓的平移動(dòng)畫(huà)效果    
   @Override    
   protected void onDraw(Canvas canvas) {
       // 如果當(dāng)前點(diǎn)坐標(biāo)為空(即第一次)        
       if (currentPoint == null) {            
           currentPoint = new Point(RADIUS, RADIUS);            
           // 創(chuàng)建一個(gè)點(diǎn)對(duì)象(坐標(biāo)是(70,70))            
           
           // 在該點(diǎn)畫(huà)一個(gè)圓:圓心 = (70,70),半徑 = 70            
           float x = currentPoint.getX();            
           float y = currentPoint.getY();            
           canvas.drawCircle(x, y, RADIUS, mPaint);
           
           // (重點(diǎn)關(guān)注)將屬性動(dòng)畫(huà)作用到View中            
           // 步驟1:創(chuàng)建初始動(dòng)畫(huà)時(shí)的對(duì)象點(diǎn)  & 結(jié)束動(dòng)畫(huà)時(shí)的對(duì)象點(diǎn)            
           Point startPoint = new Point(RADIUS, RADIUS);// 初始點(diǎn)為圓心(70,70)            
           Point endPoint = new Point(700, 1000);// 結(jié)束點(diǎn)為(700,1000)            
           
           // 步驟2:創(chuàng)建動(dòng)畫(huà)對(duì)象 & 設(shè)置初始值 和 結(jié)束值            
           ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);            
           // 參數(shù)說(shuō)明            
           // 參數(shù)1:TypeEvaluator 類(lèi)型參數(shù) - 使用自定義的PointEvaluator(實(shí)現(xiàn)了TypeEvaluator接口)            
           // 參數(shù)2:初始動(dòng)畫(huà)的對(duì)象點(diǎn)            
           // 參數(shù)3:結(jié)束動(dòng)畫(huà)的對(duì)象點(diǎn)            
           // 步驟3:設(shè)置動(dòng)畫(huà)參數(shù)            
           anim.setDuration(5000);            
           // 設(shè)置動(dòng)畫(huà)時(shí)長(zhǎng)

          // 步驟3:通過(guò) 值 的更新監(jiān)聽(tīng)器,將改變的對(duì)象手動(dòng)賦值給當(dāng)前對(duì)象
         
// 此處是將 改變后的坐標(biāo)值對(duì)象 賦給 當(dāng)前的坐標(biāo)值對(duì)象            
            // 設(shè)置 值的更新監(jiān)聽(tīng)器            
            // 即每當(dāng)坐標(biāo)值(Point對(duì)象)更新一次,該方法就會(huì)被調(diào)用一次            
            anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            
           
               @Override                
               public void onAnimationUpdate(ValueAnimator animation) {                    
                   currentPoint = (Point) animation.getAnimatedValue();
                   // 將每次變化后的坐標(biāo)值(估值器PointEvaluator中evaluate()返回的Piont對(duì)象值)到當(dāng)前坐標(biāo)值對(duì)象(currentPoint)                    
                   // 從而更新當(dāng)前坐標(biāo)值(currentPoint)
           
                   // 步驟4:每次賦值后就重新繪制,從而實(shí)現(xiàn)動(dòng)畫(huà)效果
                   
                   invalidate();                    
                   // 調(diào)用invalidate()后,就會(huì)刷新View,即才能看到重新繪制的界面,即onDraw()會(huì)被重新調(diào)用一次                    
                   // 所以坐標(biāo)值每改變一次,就會(huì)調(diào)用onDraw()一次                
               }            
           });            
           
           anim.start();            
           // 啟動(dòng)動(dòng)畫(huà)        
           
        } else {          
            // 如果坐標(biāo)值不為0,則畫(huà)圓            
            // 所以坐標(biāo)值每改變一次,就會(huì)調(diào)用onDraw()一次,就會(huì)畫(huà)一次圓,從而實(shí)現(xiàn)動(dòng)畫(huà)效果            
            
            // 在該點(diǎn)畫(huà)一個(gè)圓:圓心 = (30,30),半徑 = 30            
            float x = currentPoint.getX();            
            float y = currentPoint.getY();            
            canvas.drawCircle(x, y, RADIUS, mPaint);      
         }    
      }
  }

步驟4:在布局文件加入自定義View空間

activity_main.xml

'1.0' encoding='utf-8'?>
RelativeLayout xmlns:android='http://schemas./apk/res/android'

   xmlns:tools='http://schemas./tools'
   android:layout_width='match_parent'
   android:layout_height='match_parent'
   android:paddingBottom='@dimen/activity_vertical_margin'
   android:paddingLeft='@dimen/activity_horizontal_margin'
   android:paddingRight='@dimen/activity_horizontal_margin'
   android:paddingTop='@dimen/activity_vertical_margin'
   tools:context='scut.carson_ho.valueanimator_ofobject.MainActivity'>

    scut.carson_ho.valueanimator_ofobject.MyView
        android:layout_width='match_parent'        
        android:layout_height='match_parent'        
         />
RelativeLayout>

步驟5:在主代碼文件設(shè)置顯示視圖

MainActivity.java

public class MainActivity extends AppCompatActivity {

   @Override    
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);        
       setContentView(R.layout.activity_main);    
   }
}

源碼地址:Carson_Ho的Github地址



  • 來(lái)自:CSDN-Carson_Ho

  • http://blog.csdn.net/carson_ho/article/details/72863901#t19

  • 程序員大咖整理發(fā)布,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)

【點(diǎn)擊成為Python大神】

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多