深入學習屬性動畫

深入學習屬性動畫

1.動畫三種方式

動畫名稱 動畫的定義
逐幀動畫 將一張完整的圖片拆成一張張圖片單獨的播放
補間動畫 可以對view進行一些列的動畫操作
屬性動畫 可以對非view的對象就行動畫操作,可以改變view的屬性而不單單是改變view的動畫效果

2.屬性動畫的學習

1.ValueAnimator

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
anim.setDuration(300);  
anim.start();                                                               

valueAnimatior會自動的從初始值,過度到結束值這樣的效果,還負責管理動畫的播放次數。
播放模式。

監聽動畫的執行:

ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);  
anim.setDuration(300);          
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
@Override  
public void onAnimationUpdate(ValueAnimator animation) {  
    float currentValue = (float) animation.getAnimatedValue();  
    Log.d("TAG", "cuurent value is " + currentValue);  
}  
});  
anim.start();                                                  

2.ObjectAnimator

ValueAnimator知不是對值的平滑的動畫過渡而ObjectAnimator可以直接對任意對象任意屬性進行
動畫操作。ObjectAnimatior繼承自ValueAnimator用法類似,將一個TextView在五秒內從常規變成透明再變成常規:

ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
animator.setDuration(5000);  
animator.start(); 

3.組合動畫

實現組合動畫主要用到AnimatorSet類,這個類提供了一個play()的方法,返回一個AnimatorSet實例
AnimatorSet.Builder中包括四個方法

  • after(Animator anim),將現有動畫插入到傳入的動畫之後

  • after(long delay),將現有動畫延遲到制定動畫之後

  • before(Animator anim),將現有動畫插入到傳入的動畫之前

  • with(Animator anim),將現有動畫和傳入的動畫同時執行。

    ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);  
    ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);  
    ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);  
    AnimatorSet animSet = new AnimatorSet();  
    animSet.play(rotate).with(fadeInOut).after(moveIn);  
    animSet.setDuration(5000);  
    animSet.start(); 
    

4.Animator監聽器

監聽動畫何時開始,何時結束,Animator類提供了一個addListener()方法,這個方法接受一個AnimatorListener。添加一個監聽器的示例代碼:

anim.addListener(new AnimatorListener() {  
            @Override  
public void onAnimationStart(Animator animation) {  
}  

@Override  
public void onAnimationRepeat(Animator animation) {  
}  

@Override  
public void onAnimationEnd(Animator animation) {  
}  

@Override  
public void onAnimationCancel(Animator animation) {  
}  
});

有時並不需要監聽這麼多事件,爲此提供了一個AnimatorLIstenerAdapter,解決。示例代碼:

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

5.使用XML編寫動畫

如果使用XML來編寫動畫,需要在res目錄下創建一個animator文件,在XML文件中添加三種標籤

  • <animator> 標籤對應代碼中的ValueAnimator:實現一個而從0到100的平滑過渡

    <animator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="0"  
    android:valueTo="100"  
    android:valueType="intType"/>  
    
  • <objectAnimator>對應代碼的ObjectAnimator;實現透明度從1到0的動畫

    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"  
    android:valueFrom="1"  
    android:valueTo="0"  
    android:valueType="floatType"  
    android:propertyName="alpha"/>  
    
  • <set>對應代碼的AnimatorSet

    Xml文件編寫之後在代碼中的加載方式:

    Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_file);  
    animator.setTarget(view);  
    animator.start(); 
    

ValueAnimator的高級用法

在自定義一個View的時候,在這個View中有Point對象管理座標,然後在onDraw()方法中就是根據這個Point對象的座標值,進行繪製,如果我們對整個自定義View的動畫效果就有了。

先了解TypeEvaluator的用法:簡單來說就是告訴動畫系統,如何從初始值過渡到結束值。比如ValueAnimator.ofFloat()就是實現了從初始值到結束值的平滑過渡,其實就是系統內置了一個FloatEvaluator:代碼實現如下,

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);  
    }  
}  

三個參數的意義:

  • fraction,表示動畫的完成度。

  • startValue 動畫的初始值

  • endValue 動畫的結束值

ObjectAnimator的高級用法

補間動畫只能實現移動,縮放等操作,但是要對view的顏色進行動態改變就無法實現。

ObjectAnimator:內部的工作機制是通過尋找特定的屬性的get和set方法,然後通過對值不斷的改變從而實現動畫。比如,我們自定義一個View,只需要在其內部這樣寫:

 public class MyAnimView extends View {  
 ...  
 private String color;  
 public String getColor() {  
        return color;  
 }  
  public void setColor(String color) {  
        this.color = color;  
        mPaint.setColor(Color.parseColor(color));  
        invalidate();  
    }  
    ...  
}   

Interpolator的用法

Interpolator:直譯是補間器的意思。它的主要作用是可以控制動畫的變化速率,比如去實現一種非線性運動的動畫效果。那麼什麼叫做非線性運動的動畫效果呢?就是說動畫改變的速率不是一成不變的,像加速運動以及減速運動都屬於非線性運動。不過Interpolator並不是屬性動畫中新增的技術,實際上從Android 1.0版本開始就一直存在Interpolator接口了,而之前的補間動畫當然也是支持這個功能的。只不過在屬性動畫中新增了一個TimeInterpolator接口,這個接口是用於兼容之前的Interpolator的,這使得所有過去的Interpolator實現類都可以直接拿過來放到屬性動畫當中使用 。

  • AccelerateDecelerateInterpolator 先加速後減速的interpolator,系統默認的補間器。

  • AccelerateInterpolator 加速的補間器

  • DecelerateInterpolator 減速的補間器。

    系統內置的補間器非常多。interpolator的內部實現機制是什麼:

    /** 
    * A time interpolator defines the rate of change of an animation. This allows animations 
    * to have non-linear motion, such as acceleration and deceleration. 
    */  
     public interface TimeInterpolator {  
    
    /** 
     * Maps a value representing the elapsed fraction of an animation to a value that represents 
     * the interpolated fraction. This interpolated value is then multiplied by the change in 
     * value of an animation to derive the animated value at the current elapsed animation time. 
     * 
     * @param input A value between 0 and 1.0 indicating our current point 
     *        in the animation where 0 represents the start and 1.0 represents 
     *        the end 
     * @return The interpolation value. This value can be more than 1.0 for 
     *         interpolators which overshoot their targets, or less than 0 for 
     *         interpolators that undershoot their targets. 
     */  
    float getInterpolation(float input);  
     }  
    

    getInterpolation()方法接收了一個input值,這個值隨着動畫的運行不斷變化,不過變化是有規率可尋的,就是根據設定動畫時長勻速增加。變化範圍是0到1即:動畫開始的時候input值爲0,動畫結束的時候input值爲1。inuput值與fraction值之間有什麼關係?input值就是fraction。input值經過系統計算,傳入到getINnterpolation中,然後我們可以自己實現這個方法,經過計算返回input值,這個值就是fraction參數。因此最簡單的就是input值與fraction相同。系統中內置LinearInterpolator就是一種勻速運動的Interpolator,那麼我們來看一下它的源碼是怎麼實現的:

    /** 
     * An interpolator where the rate of change is constant 
     */  
    @HasNativeInterpolator  
    public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {  
    public LinearInterpolator() {  
    }  
    public LinearInterpolator(Context context, AttributeSet attrs) {  
    }  
    public float getInterpolation(float input) {  
    return input;  
    }  
    /** @hide */  
    @Override  
     public long createNativeInterpolator() {  
    return NativeInterpolatorFactoryHelper.createLinearInterpolator();  
     }  
    }    
    

    知道補間器裏面的實現過程自定義一個先加速,後減速的補間器。

    /**
    * @author [email protected]
    * @Company 杭州木瓜科技有限公司
    * @date 2016/8/3
    */
    public class DefineInterpolation implements TimeInterpolator {
    
     @Override
    public float getInterpolation(float input) {
    if (input<0.5){
        input= (float) ((Math.sin(input*Math.PI)))/2;
    }else {
        input= (float) (2-Math.sin(input*Math.PI))/2;
    }
    return input;
    }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章