Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 屬性動畫入門

android 屬性動畫入門

編輯:關於Android編程

前面關於tween動畫寫了2篇博客,如果那2篇博客都看懂了,估計Tween動畫理解使用起來問題就不大,之前也說了Tween動畫的缺點就是在交互上有bug,今天就講下屬性動畫,屬性動畫就能解決Tween動畫交互上的問題,由於下周工作上很忙,估計要花一周時間把這篇博客寫完,一些常見的動畫demo,都在寫出來,希望每個人都能看的懂,切入正題,

屬性動畫英文叫Property Animator,它包括ValueAnimator和ObjectAnimator,我們先看ValueAnimator這個類,從類名字直觀的就是叫值動畫,對吧,那麼這和Tween動畫不同的是Tween動畫是叫view animation,作用於控件上的,如果看過ValueAnimator類的源碼就知道它是繼承了Animator這個類,現在看下Animator類的源碼,看看它給我們提供了什麼方法讓我們去調用,這個類的源碼是我把注釋刪除了,代碼量很少,才200多行

package android.animation;
import android.content.res.ConstantState;
import java.util.ArrayList;
public abstract class Animator implements Cloneable {
/**
* The set of listeners to be sent events through the life of an animation.
*/
ArrayList mListeners = null;
/**
* The set of listeners to be sent pause/resume events through the life
* of an animation.
*/
ArrayList mPauseListeners = null;
/**
* Whether this animator is currently in a paused state.
*/
boolean mPaused = false;

int mChangingConfigurations = 0;
private AnimatorConstantState mConstantState;
public void start() {
}
public void cancel() {
}

public void end() {
}
public void pause() {
if (isStarted() && !mPaused) {
mPaused = true;
if (mPauseListeners != null) {
ArrayList tmpListeners =
(ArrayList) mPauseListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
tmpListeners.get(i).onAnimationPause(this);
}
}
}
}
public void resume() {
if (mPaused) {
mPaused = false;
if (mPauseListeners != null) {
ArrayList tmpListeners =
(ArrayList) mPauseListeners.clone();
int numListeners = tmpListeners.size();
for (int i = 0; i < numListeners; ++i) {
tmpListeners.get(i).onAnimationResume(this);
}
}
}
}
public boolean isPaused() {
return mPaused;
}
public abstract long getStartDelay();
public abstract void setStartDelay(long startDelay);
public abstract Animator setDuration(long duration);
public abstract long getDuration();
public abstract void setInterpolator(TimeInterpolator value);
public TimeInterpolator getInterpolator() {
return null;
}
public abstract boolean isRunning();
public boolean isStarted() {
// Default method returns value for isRunning(). Subclasses should override to return a
// real value.
return isRunning();
}
public void addListener(AnimatorListener listener) {
if (mListeners == null) {
mListeners = new ArrayList();
}
mListeners.add(listener);
}
public void removeListener(AnimatorListener listener) {
if (mListeners == null) {
return;
}
mListeners.remove(listener);
if (mListeners.size() == 0) {
mListeners = null;
}
}
public ArrayList getListeners() {
return mListeners;
}
public void addPauseListener(AnimatorPauseListener listener) {
if (mPauseListeners == null) {
mPauseListeners = new ArrayList();
}
mPauseListeners.add(listener);
}
public void removePauseListener(AnimatorPauseListener listener) {
if (mPauseListeners == null) {
return;
}
mPauseListeners.remove(listener);
if (mPauseListeners.size() == 0) {
mPauseListeners = null;
}
}
public void removeAllListeners() {
if (mListeners != null) {
mListeners.clear();
mListeners = null;
}
if (mPauseListeners != null) {
mPauseListeners.clear();
mPauseListeners = null;
}
}

public int getChangingConfigurations() {
return mChangingConfigurations;
}
public void setChangingConfigurations(int configs) {
mChangingConfigurations = configs;
}
public void appendChangingConfigurations(int configs) {
mChangingConfigurations |= configs;
}
public ConstantState createConstantState() {
return new AnimatorConstantState(this);
}
@Override
public Animator clone() {
try {
final Animator anim = (Animator) super.clone();
if (mListeners != null) {
anim.mListeners = new ArrayList(mListeners);
}
if (mPauseListeners != null) {
anim.mPauseListeners = new ArrayList(mPauseListeners);
}
return anim;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
public void setupStartValues() {
}
public void setupEndValues() {
}


public void setTarget(Object target) {
}

public boolean canReverse() {
return false;
}
/**
* @hide
*/
public void reverse() {
throw new IllegalStateException("Reverse is not supported");
}
public static interface AnimatorListener {
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
}

public static interface AnimatorPauseListener {
void onAnimationPause(Animator animation);
void onAnimationResume(Animator animation);
}
public void setAllowRunningAsynchronously(boolean mayRunAsync) {
// It is up to subclasses to support this, if they can.
}
private static class AnimatorConstantState extends ConstantState {
final Animator mAnimator;
int mChangingConf;
public AnimatorConstantState(Animator animator) {
mAnimator = animator;
// ensure a reference back to here so that constante state is not gc'ed.
mAnimator.mConstantState = this;
mChangingConf = mAnimator.getChangingConfigurations();
}
@Override
public int getChangingConfigurations() {
return mChangingConf;
}
@Override
public Animator newInstance() {
final Animator clone = mAnimator.clone();
clone.mConstantState = this;
return clone;
}
}
}

通過看它的源碼發現Animator是一個抽象類,既然它是抽象類,那麼一定存在抽象的方法,現在就把幾個抽象方法提出來

public abstract void setStartDelay(long startDelay); 這是延遲幾秒開始執行動畫

public abstract long getStartDelay();獲取動畫延遲執行的時間,單位為毫秒

public abstract Animator setDuration(long duration); 設置動畫執行的時間 單位為毫秒

public abstract long getDuration();獲取動畫執行的時間

public abstract void setInterpolator(TimeInterpolator value);設置動畫插值器

public abstract boolean isRunning();動畫是否在執行

下面是非抽象函數並且是空實現的

public void start() {} 動畫開始

public void cancel() {}取消執行動畫

public void end() {}結束動畫執行

public void setTarget(Object target) {}設置動畫的標記

下面是非空實現方法:

public void pause() {}動畫暫停的方法

public void resume() {}動畫重新執行

public boolean isPaused() {}動畫是否暫停了,默認返回值為false

public TimeInterpolator getInterpolator() {} 返回動畫插值器對象,默認返回為null

public boolean isStarted() {} 動畫是否執行了,默認返回值是調用了isRunning()方法,而這個方法又是抽象的,需要子類去實現,

public void addListener(AnimatorListener listener) {
    if (mListeners == null) {
        mListeners = new ArrayList();
    }
    mListeners.add(listener);
}
這是添加動畫監聽的方法,它是用一個List集合去維護了所添加的監聽器,而AnimatorListener是一個接口,如下:
public static interface AnimatorListener {
    /**
     * 
Notifies the start of the animation.

* * @param animation The started animation. */ void onAnimationStart(Animator animation); /** *
Notifies the end of the animation. This callback is not invoked * for animations with repeat count set to INFINITE.

* * @param animation The animation which reached its end. */ void onAnimationEnd(Animator animation); /** *
Notifies the cancellation of the animation. This callback is not invoked * for animations with repeat count set to INFINITE.

* * @param animation The animation which was canceled. */ void onAnimationCancel(Animator animation); /** *
Notifies the repetition of the animation.

* * @param animation The animation which was repeated. */ void onAnimationRepeat(Animator animation); }
這個接口分別定義了四個方法依次是動畫開始,結束,取消,重復等回調接口,
public void removeListener(AnimatorListener listener) {
    if (mListeners == null) {
        return;
    }
    mListeners.remove(listener);
    if (mListeners.size() == 0) {
        mListeners = null;
    }
}

這個是移除一個動畫監聽,
public ArrayList getListeners() {
    return mListeners;
}

這是獲取所有監聽動畫
public void addPauseListener(AnimatorPauseListener listener) {
    if (mPauseListeners == null) {
        mPauseListeners = new ArrayList();
    }
    mPauseListeners.add(listener);
}

這是添加一個暫停動畫監聽的方法,而AnimatorPauseListener是一個接口
public static interface AnimatorPauseListener {
    /**
     * 
Notifies that the animation was paused.

* * @param animation The animaton being paused. * @see #pause() */ void onAnimationPause(Animator animation); /** *
Notifies that the animation was resumed, after being * previously paused.

* * @param animation The animation being resumed. * @see #resume() */ void onAnimationResume(Animator animation); } 分別定義了動畫暫停和重新執行的回調方法
public void removePauseListener(AnimatorPauseListener listener) {
    if (mPauseListeners == null) {
        return;
    }
    mPauseListeners.remove(listener);
    if (mPauseListeners.size() == 0) {
        mPauseListeners = null;
    }
}

這是移除一個暫停動畫的監聽
public void removeAllListeners() {
    if (mListeners != null) {
        mListeners.clear();
        mListeners = null;
    }
    if (mPauseListeners != null) {
        mPauseListeners.clear();
        mPauseListeners = null;
    }
}

這是移除所有動畫的監聽,包括動畫開始和結束的監聽和暫停的監聽

 

下面就開始講ValueAnimator類的一些使用了,

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ValueAnimator animator = ValueAnimator.ofInt(0,100);
        animator.setDuration(1000);
        animator.start();
    }
}
這是一個平移動畫,但我並沒有把這個動畫作用於某一個控件上,那這個動畫到底有沒有執行呢?我們知道動畫都有監聽的方法,

 

 

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        int curValue = (int)animation.getAnimatedValue();
        Log.d(TAG,"curValue:"+curValue);
    }
});
animation.getAnimatedValue()方法是返回動畫的屬性值,默認返回值是Object,但是我們傳入的是int值,所以就可以強轉成int值了,通過打印的log分析:

 

07-10 05:05:24.945 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:0
07-10 05:05:25.098 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:5
07-10 05:05:25.285 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:24
07-10 05:05:25.325 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:29
07-10 05:05:25.355 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:34
07-10 05:05:25.365 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:36
07-10 05:05:25.385 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:39
07-10 05:05:25.405 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:42
07-10 05:05:25.415 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:44
07-10 05:05:25.435 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:47
07-10 05:05:25.445 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:50
07-10 05:05:25.465 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:52
07-10 05:05:25.475 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:55
07-10 05:05:25.495 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:57
07-10 05:05:25.515 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:60
07-10 05:05:25.525 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:62
07-10 05:05:25.548 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:65
07-10 05:05:25.565 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:67
07-10 05:05:25.582 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:70
07-10 05:05:25.598 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:72
07-10 05:05:25.615 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:74
07-10 05:05:25.627 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:77
07-10 05:05:25.648 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:79
07-10 05:05:25.665 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:81
07-10 05:05:25.676 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:83
07-10 05:05:25.698 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:85
07-10 05:05:25.715 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:87
07-10 05:05:25.732 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:88
07-10 05:05:25.748 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:90
07-10 05:05:25.765 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:91
07-10 05:05:25.777 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:93
07-10 05:05:25.798 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:94
07-10 05:05:25.815 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:95
07-10 05:05:25.825 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:96
07-10 05:05:25.848 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:97
07-10 05:05:25.865 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:98
07-10 05:05:25.882 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:98
07-10 05:05:25.898 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:99
07-10 05:05:25.915 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:99
07-10 05:05:25.927 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:99
07-10 05:05:25.948 1178-1178/com.example.valueanimatordemo D/MainActivity: curValue:100

通過上面的log知道,上面是打印的在1秒時間內所改變的值,從這個log就證明動畫是執行了的,但是並沒有作用於某一個控件上,從這就明顯看出來和Tween動畫的區別,現在就根據這些值做一個平移的動畫,你會發現view類並沒有什麼方法設置可以執行屬性動畫的方法,那我們只能根據view提供的並外一個方法layout動態改變他在父view上的位置了,這個方法大家很熟悉了,

布局文件:

 


這個imageview顯示的圖片是胡歌的前女友,只能說明星真會玩,玩了就不玩了,

 

 



public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private Button btn_start_anim; private ImageView iv_show_grid; private int left,top; private boolean isFirst; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start_anim = (Button) findViewById(R.id.btn_start_anim); iv_show_grid = (ImageView) findViewById(R.id.iv_show_grid); btn_start_anim.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { execAnimator(); } }); iv_show_grid.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(),"客官點我",Toast.LENGTH_SHORT).show(); } }); } private int tempValue = 0; public void execAnimator(){ ValueAnimator animator = ValueAnimator.ofInt(0,100); animator.setDuration(1000); animator.start(); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int curValue = (int)animation.getAnimatedValue(); left = iv_show_grid.getLeft(); top = iv_show_grid.getTop(); iv_show_grid.layout(left+curValue-tempValue,top+curValue-tempValue,left+iv_show_grid.getWidth()+curValue-tempValue,iv_show_grid.getHeight()+curValue+top-tempValue); tempValue = curValue; } }); } } 
效果:

 

\

ok,現在發現屬性動畫是不是能解決Tween動畫的交互上的bug,imageview平移後點擊是ok,

上面使用了ValueAnimator類的一個ofInt()方法,上面我們ofInt()方法傳入了0,100表示從0變化到100,別以為ofInt()方法只接受2個參數,其實它是可變參數的,

public static ValueAnimator ofInt(int... values) {
    ValueAnimator anim = new ValueAnimator();
    anim.setIntValues(values);
    return anim;
}
那我們可以利用方法實現類似上下移動的效果,
private int tempValue = 0;
public void execAnimator(){
    ValueAnimator animator = ValueAnimator.ofInt(0,200,200,0,0,200,200,0,0,200,200,0);
    animator.setDuration(1000);
    animator.start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int curValue = (int)animation.getAnimatedValue();
            left = iv_show_grid.getLeft();
            top = iv_show_grid.getTop();
            iv_show_grid.layout(left,top+curValue-tempValue,left+iv_show_grid.getWidth(),iv_show_grid.getHeight()+curValue+top-tempValue);
            tempValue = curValue;
        }
    });
}

效果:

 

\

是不是感覺設置了動畫的重復方法,其實並沒有,

還有一個ofFloat方法其實和ofInt()方法功能是一樣的,只是精度不一樣而已,現在再玩一個方法,就是關於顏色變化的,

public static ValueAnimator ofArgb(int... values) {
    ValueAnimator anim = new ValueAnimator();
    anim.setIntValues(values);
    anim.setEvaluator(ArgbEvaluator.getInstance());
    return anim;
}
突然這個api是要到21才能用,關鍵是我現在最低版本是15,算了不改了,講下另外一個方法,也是很重要的,就是插值器,
public void setInterpolator(TimeInterpolator value) {
    if (value != null) {
        mInterpolator = value;
    } else {
        mInterpolator = new LinearInterpolator();
    }
}

發現我們沒有設置的時候,默認是使用LinearInterpolator,先看下TimeInterpolator這個類,
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);
}

就一個方法getInterpolation()該方法一個形參input,從方法的注釋上看到這個input的取值范圍為[0,1],它有如下子類

 

\

我們現在可以自定義一個LinearInterpolator,通過log打印出input的值

class MyLinearInterpolator extends LinearInterpolator{
    @Override
    public float getInterpolation(float input) {
        Log.e(TAG,"input="+input);
        return super.getInterpolation(input);
    }
}
設置插值器
animator.setInterpolator(new MyLinearInterpolator());
log:

07-10 09:12:10.701 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.0
07-10 09:12:10.710 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.0
07-10 09:12:10.730 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.017
07-10 09:12:10.760 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.05
07-10 09:12:10.781 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.067
07-10 09:12:10.792 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.083
07-10 09:12:10.820 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.1
07-10 09:12:10.831 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.117
07-10 09:12:10.851 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.133
07-10 09:12:10.881 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.167
07-10 09:12:10.901 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.183
07-10 09:12:10.921 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.2
07-10 09:12:10.941 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.233
07-10 09:12:10.970 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.25
07-10 09:12:10.981 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.267
07-10 09:12:11.010 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.3
07-10 09:12:11.030 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.317
07-10 09:12:11.050 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.333
07-10 09:12:11.071 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.35
07-10 09:12:11.092 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.367
07-10 09:12:11.111 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.4
07-10 09:12:11.131 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.417
07-10 09:12:11.141 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.433
07-10 09:12:11.160 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.45
07-10 09:12:11.190 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.467
07-10 09:12:11.200 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.483
07-10 09:12:11.220 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.5
07-10 09:12:11.230 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.517
07-10 09:12:11.251 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.533
07-10 09:12:11.260 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.55
07-10 09:12:11.271 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.567
07-10 09:12:11.301 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.583
07-10 09:12:11.310 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.6
07-10 09:12:11.330 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.617
07-10 09:12:11.340 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.633
07-10 09:12:11.370 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.667
07-10 09:12:11.410 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.7
07-10 09:12:11.450 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.733
07-10 09:12:11.480 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.767
07-10 09:12:11.490 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.783
07-10 09:12:11.520 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.8
07-10 09:12:11.531 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.817
07-10 09:12:11.551 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.833
07-10 09:12:11.560 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.85
07-10 09:12:11.580 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.867
07-10 09:12:11.620 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.9
07-10 09:12:11.650 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.933
07-10 09:12:11.690 3672-3672/com.example.valueanimatordemo E/MainActivity: input=0.967
07-10 09:12:11.710 3672-3672/com.example.valueanimatordemo E/MainActivity: input=1.0

通過上面的log也驗證了input的取值范圍是[0,1]


各個插值器的意思如下:

 

意義如下:

AccelerateDecelerateInterpolator 在動畫開始與結束的地方速率改變比較慢,在中間的時候加速

AccelerateInterpolator 在動畫開始的地方速率改變比較慢,然後開始加速

AnticipateInterpolator 開始的時候向後然後向前甩

AnticipateOvershootInterpolator 開始的時候向後然後向前甩一定值後返回最後的

BounceInterpolator 動畫結束的時候彈起

CycleInterpolator 動畫循環播放特定的次數,速率改變沿著正弦曲線

DecelerateInterpolator 在動畫開始的地方快然後慢

LinearInterpolator 以常量速率改變

OvershootInterpolator 向前甩一定值後再回到原來位置

 

現在每個插值器都玩下,看看效果:

共同的代碼如下就是設置插值器代碼不同而且

AccelerateDecelerateInterpolator

\

AccelerateInterpolator

\

AnticipateInterpolator

\

AnticipateOvershootInterpolator

\

BounceInterpolator

\

CycleInterpolator

\

DecelerateInterpolator

\

OvershootInterpolator

\

LinearInterpolator

\

現在所有的動畫插值器都演示了一邊,可能有的不夠明顯,現在講ValueAnimator類的

public void setEvaluator(TypeEvaluator value) {} 這個函數接受的形參是TypteEvaluator,

public interface TypeEvaluator {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * fraction representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: result = x0 + t * (x1 - x0),
     * where x0 is startValue, x1 is endValue,
     * and t is fraction.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         fraction parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}
形參說明

 

fraction:從開始值startValue到endValue之間的值

startValue:開始值

endValue:結束值

現在看下TypeEvalator的一些實現類

\

從子類的名字就可以看出假如傳入的是int值,那麼就對應IntEvaluator類,

現在自定義一個IntEvaluator,看看evaluator方法中的三個參數:

/**
 * 設置動畫執行
 */
public void execAnimator(){
    ValueAnimator animator = ValueAnimator.ofInt(0,200);
    animator.setDuration(1000);
    animator.setEvaluator(new MyIntEvaluator());
    animator.start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int curValue = (int)animation.getAnimatedValue();
            left = iv_show_grid.getLeft();
            top = iv_show_grid.getTop();
            iv_show_grid.layout(left,top+curValue-tempValue,left+iv_show_grid.getWidth(),iv_show_grid.getHeight()+curValue+top-tempValue);
            tempValue = curValue;
        }
    });
}
class MyIntEvaluator extends IntEvaluator{
    @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        Log.e(TAG,"fraction="+fraction);
        Log.e(TAG,"startValue="+fraction);
        Log.e(TAG,"endValue="+endValue);
        Log.e(TAG,"結果值="+super.evaluate(fraction, startValue, endValue));
        return super.evaluate(fraction, startValue, endValue);
    }
}
log:

 

07-10 14:06:53.232 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.0
07-10 14:06:53.232 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.0
07-10 14:06:53.242 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.242 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=0
07-10 14:06:53.255 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.0
07-10 14:06:53.255 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.0
07-10 14:06:53.255 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.255 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=0
07-10 14:06:53.272 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=7.1290135E-4
07-10 14:06:53.272 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=7.1290135E-4
07-10 14:06:53.272 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.282 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=0
07-10 14:06:53.305 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.0061558187
07-10 14:06:53.305 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.0061558187
07-10 14:06:53.305 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.305 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=1
07-10 14:06:53.342 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.017309189
07-10 14:06:53.342 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.017309189
07-10 14:06:53.342 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.342 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=3
07-10 14:06:53.362 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.02447176
07-10 14:06:53.362 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.02447176
07-10 14:06:53.372 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.372 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=4
07-10 14:06:53.402 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.043654233
07-10 14:06:53.402 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.043654233
07-10 14:06:53.402 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.412 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=8
07-10 14:06:53.442 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.06724939
07-10 14:06:53.442 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.06724939
07-10 14:06:53.442 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.442 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=13
07-10 14:06:53.462 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.09549156
07-10 14:06:53.462 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.09549156
07-10 14:06:53.482 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.482 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=19
07-10 14:06:53.533 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.16582394
07-10 14:06:53.533 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.16582394
07-10 14:06:53.533 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.533 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=33
07-10 14:06:53.562 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.20610732
07-10 14:06:53.562 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.20610732
07-10 14:06:53.562 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.562 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=41
07-10 14:06:53.602 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.27300477
07-10 14:06:53.602 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.27300477
07-10 14:06:53.612 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.622 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=54
07-10 14:06:53.631 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.32179415
07-10 14:06:53.631 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.32179415
07-10 14:06:53.642 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.642 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=64
07-10 14:06:53.662 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.34549147
07-10 14:06:53.662 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.34549147
07-10 14:06:53.693 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.693 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=69
07-10 14:06:53.772 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.5
07-10 14:06:53.772 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.5
07-10 14:06:53.793 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.802 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=100
07-10 14:06:53.822 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.6044678
07-10 14:06:53.832 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.6044678
07-10 14:06:53.832 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.832 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=120
07-10 14:06:53.862 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.65450853
07-10 14:06:53.862 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.65450853
07-10 14:06:53.862 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.872 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=130
07-10 14:06:53.902 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.7269952
07-10 14:06:53.932 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.7269952
07-10 14:06:53.932 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.932 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=145
07-10 14:06:53.962 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.7938927
07-10 14:06:53.972 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.7938927
07-10 14:06:53.982 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:53.992 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=158
07-10 14:06:54.022 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.8719225
07-10 14:06:54.033 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.8719225
07-10 14:06:54.033 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.033 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=174
07-10 14:06:54.062 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.9045085
07-10 14:06:54.062 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.9045085
07-10 14:06:54.062 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.062 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=180
07-10 14:06:54.072 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.91962016
07-10 14:06:54.082 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.91962016
07-10 14:06:54.082 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.093 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=183
07-10 14:06:54.134 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.9671645
07-10 14:06:54.134 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.9671645
07-10 14:06:54.142 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.142 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=193
07-10 14:06:54.175 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.98309815
07-10 14:06:54.182 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.98309815
07-10 14:06:54.192 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.212 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=196
07-10 14:06:54.222 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.9973154
07-10 14:06:54.222 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.9973154
07-10 14:06:54.232 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.232 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=199
07-10 14:06:54.252 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.9993685
07-10 14:06:54.262 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.9993685
07-10 14:06:54.262 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.272 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=199
07-10 14:06:54.292 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=1.0
07-10 14:06:54.292 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=1.0
07-10 14:06:54.292 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:06:54.322 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=200

從上面的log可以看出,endValue的值是不變的,也就是我們這行代碼傳入的第二個參數:

ValueAnimator animator = ValueAnimator.ofInt(0,200);
startValue的值是從0到1,fraction的值也是從0到1,這二個值其實相等的,只是fraction是float值,startValue值是int值,而結果值的計算公式為:
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
    int startInt = startValue;
    return (int)(startInt + fraction * (endValue - startInt));
}

這是源碼中已有的,我們就拿log中的一個值來計算

 

07-10 14:16:04.042 2128-2128/com.example.valueanimatordemo E/MainActivity: fraction=0.11175674
07-10 14:16:04.052 2128-2128/com.example.valueanimatordemo E/MainActivity: startValue=0.11175674
07-10 14:16:04.052 2128-2128/com.example.valueanimatordemo E/MainActivity: endValue=200
07-10 14:16:04.052 2128-2128/com.example.valueanimatordemo E/MainActivity: 結果值=22

0.11175674+0.11175674*(200-0.11175674)=0.11175674*(1+200-0.11175674)=22.450613055062455 但是結果是Integer,所以結果就是22了

在這補充一個知識點:

ValueAnimator animator = ValueAnimator.ofInt(100,200); 這個100是要執行動畫的起始坐標,200是動畫結束時的坐標,這個是以父view的左上角為參考點,

下面我們重寫evaluate()方法的返回值看看結果是什麼樣的:

class MyIntEvaluator extends IntEvaluator{
    @Override
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int temp=(int)fraction;
        int startInt= startValue;
        return (int)(100+startInt + fraction * (endValue - startInt));
    }
}
效果:

 

\

其實這個不看效果,也知道肯定比傳入的200(最終坐標)要大,現在看一個以後會經常使用的一個類就是ArgbEvaluator,

/**
 * 設置動畫執行
 */
public void execAnimator(){
    ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xffffff99);
    animator.setEvaluator(new ArgbEvaluator());
    animator.setDuration(5000);

    animator.setEvaluator(new ArgbEvaluator());
    animator.start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int curValue = (int)animation.getAnimatedValue();
            btn_argb.setBackgroundColor(curValue);
        }
    });
}
效果:

 

\

ValueAnimator類還有一個可以自定義對象的方法就是ofObject(),看源碼:

public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
    ValueAnimator anim = new ValueAnimator();
    anim.setObjectValues(values);
    anim.setEvaluator(evaluator);
    return anim;
}

參數說明:

evaluator:這個是你自定義的TypeEvaluator

values:是你對這個自定義對象的值的變化

之前的博客記得寫過什麼水波紋類似的效果,其實就是在時間很短的情況下改變圓的半徑實現的,今天也用這個也實現下這個效果
public class CustomView extends View {
    private static final String TAG ="CustomView" ;
    private Paint mPaint;
    private MyPoint myPoint;
    public CustomView(Context context) {
        super(context);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint();
        mPaint.setStrokeWidth(5);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.WHITE);
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(myPoint!=null){
            Log.e(TAG,"第一次他的半徑是==="+myPoint.getRaduis());
            canvas.drawCircle(200, 200, myPoint.getRaduis(), mPaint);
        }
    }
    public void execAnimator() {
        ValueAnimator animator = ValueAnimator.ofObject(new RadiusEvaluator(), new MyPoint(10), new MyPoint(200));
        animator.setDuration(100);
        animator.setRepeatCount(10);
        animator.start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                myPoint = (MyPoint)animation.getAnimatedValue();
                invalidate();
            }
        });
    }
}

自定義半徑類:
public class MyPoint {

    private int raduis;

    public MyPoint(int raduis) {
        this.raduis = raduis;
    }

    public int getRaduis() {
        return raduis;
    }
    public void setRaduis(int raduis) {
        this.raduis = raduis;
    }
}

自定義TypeEaluator
public class RadiusEvaluator implements TypeEvaluator {
    @Override
    public MyPoint evaluate(float fraction, MyPoint startValue, MyPoint endValue) {
        int startRaduis = startValue.getRaduis();
        int endRaduis  = endValue.getRaduis();
        int curValue = (int)(startRaduis + fraction * (endRaduis - startRaduis));
        return new MyPoint(curValue);
    }
}

最後就是按鈕點擊執行動畫了
btn_start_anim.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        customview.execAnimator();
    }
});

效果:

 

\

現在我向動畫中添加一個插值器BounceInterpolator,這個表示動畫結束的時候彈起,而且要把動畫時間放長點才好看出來效果:

public void execAnimator() {
    ValueAnimator animator = ValueAnimator.ofObject(new RadiusEvaluator(), new MyPoint(10), new MyPoint(100));
    animator.setDuration(1000);
    animator.setInterpolator(new BounceInterpolator());
    animator.start();
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            myPoint = (MyPoint)animation.getAnimatedValue();
            invalidate();
        }
    });
}
效果:

 

\

ValueAnimator類基本的使用都講完了,你發現使用ValueAnimator做view平移的時候是用view的layout()方法實現的,而ValueAnimator類並沒有給我們直接提供方法讓我們自己調用,那麼就引人了ObjectAnimator這個類了,

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved