Android 屬性動畫(二)

上一篇 Android 屬性動畫(一) 介紹了Property Animator 的基本用法。今天繼續(xù)了解Property Animator 的Evaluator、Interpolator 和 xml 文件定義Animator 的相關知識和用法艘蹋。

Evaluator 求值器

直接貼源碼:

public interface TypeEvaluator<T> {    
/**     
    * This function returns the result of linearly interpolating the start and end values, with   
    * <code>fraction</code> representing the proportion between the start and end values. The     
    * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,    
    * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,     
    * and <code>t</code> is <code>fraction</code>.     
    * 
    * @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     
    *         <code>fraction</code> parameter.     
    */    
public T evaluate(float fraction, T startValue, T endValue);
}

源碼很簡短肠阱,就一個方法嚼贡,默認實現(xiàn)就是 根據(jù)fraction 通過 result = x0 + t * (x1 - x0) 公式計算返回一個中間值。
那么 fraction 這個參數(shù)是多少呢?通過ValueAnimator 的setEvaluator() 方法找到源碼:

boolean animationFrame(long currentTime) {    
    boolean done = false;
    switch (mPlayingState) {
    case RUNNING:
    case SEEKED:
        float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
        if (mDuration == 0 && mRepeatCount != INFINITE) {
            // Skip to the end 
           mCurrentIteration = mRepeatCount;
            if (!mReversing) {
                mPlayingBackwards = false;
            }
        }
        if (fraction >= 1f) {
            if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE)
            {                
                // Time to repeat
                if (mListeners != null) {
                    int numListeners = mListeners.size();
                    for (int i = 0; i < numListeners; ++i) {
                        mListeners.get(i).onAnimationRepeat(this);
                    }
                }
                if (mRepeatMode == REVERSE) {
                    mPlayingBackwards = !mPlayingBackwards;
                }
                mCurrentIteration += (int) fraction;
                fraction = fraction % 1f;
                mStartTime += mDuration;
                // Note: We do not need to update the value of mStartTimeCommitted here
                // since we just added a duration offset.
            } else {
                done = true;
                fraction = Math.min(fraction, 1.0f);
            }
        }
        if (mPlayingBackwards) {
            fraction = 1f - fraction;
        }
        animateValue(fraction);
        break;
    }
    return done;
}

void animateValue(float fraction) {
    fraction = mInterpolator.getInterpolation(fraction);
    mCurrentFraction = fraction;
    int numValues = mValues.length;
    for (int i = 0; i < numValues; ++i) {
        mValues[i].calculateValue(fraction);
    }
    if (mUpdateListeners != null) {
        int numListeners = mUpdateListeners.size();
        for (int i = 0; i < numListeners; ++i) {
            mUpdateListeners.get(i).onAnimationUpdate(this);
        }
    }
}

在 ValueAnimator 類中有兩個方法,可以看到在 animationFrame 方法就是 得到一個已完成時間在總時長的比例值(0~1)并賦值給 fraction单匣,在 animateValue 方法中 調(diào)用了 mInterpolator.getInterpolation() (就是 插值器,后面會介紹) 目的就是修正 fraction 宝穗。所以我們知道 fraction 是一個0~1 的值』С樱現(xiàn)在看下自定義Evaluator 的代碼:

//定義了一個 PointF 類型的 Evaluator ,實現(xiàn) view 的拋物線變化
//默認 TypeEvaluator View 在X逮矛,Y方向都是勻速的鸡号。
//自定義后,View的Y方向是變速的须鼎。

ValueAnimator valueAnimator = ValueAnimator.ofObject(new TypeEvaluator<PointF>(){
    @Override    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
        // y 方向是一個變速        PointF point = new PointF();
        point.x = startValue.x + fraction * (endValue.x - startValue.x) ;
        point.y = (float) (startValue.y + Math.pow(fraction , 2) * (endValue.y - startValue.y));
        return point;
    }},
new PointF(0,0),new PointF(400,1000));
valueAnimator.setDuration(3000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){
         @Override    
        public void onAnimationUpdate(ValueAnimator animation)    {
        PointF point = (PointF) animation.getAnimatedValue();
        animView.setX(point.x);
        animView.setY(point.y);
    }});
valueAnimator.start();

Interpolator 插值器

本來想寫下Interpolayor的源碼分析的鲸伴,但看到一篇 Interpolayor的分析文章后,感覺自己也不會寫的比這個好晋控,所以還是不寫了汞窗,借鑒和學習這篇文章 李海珍大神的 android動畫(一)Interpolator。膜拜I囊搿V倮簟!
一下是從 大神文章中摘抄的部分,圖文并茂蜘矢,講解很詳細狂男,大家學習下!

二:簡單插值器分析
** 注意下面的圖品腹,對應你腦海中的插值的大小應該是斜率岖食。**

package android.view.animation;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
/**
 *
 * 一個開始很慢然后不斷加速的插值器。 
 * <hr/>
 * An interpolator where the rate of change starts out slowly and
 * and then accelerates.
 *
 */
public class AccelerateInterpolator implements Interpolator {
     private final float mFactor; private final double mDoubleFactor;
     public AccelerateInterpolator() {
        mFactor = 1.0f;
        mDoubleFactor = 2.0;
     }
     /**     
       * Constructor
       *
       * @param factor
       * 動畫的快慢度舞吭。將factor設置為1.0f會產(chǎn)生一條y=x^2的拋物線泡垃。增加factor到1.0f之后為加大這種漸入效果(也就是說它開頭更加慢,結尾更加快)
       * <br/>Degree to which the animation should be eased. Seting
       * factor to 1.0f produces a y=x^2 parabola(拋物線). Increasing factor above
       * 1.0f exaggerates the ease-in effect (i.e., it starts even   * slower and ends evens faster)
      */
      public AccelerateInterpolator(float factor) {
        mFactor = factor;
        mDoubleFactor = 2 * mFactor;
      } 
      public AccelerateInterpolator(Context context, AttributeSet attrs) {
        TypedArray a =context.obtainStyledAttributes(attrs,com.android.internal.R.styleable.AccelerateInterpolator);
        mFactor = a.getFloat(com.android.internal.R.styleable.AccelerateInterpolator_factor, 1.0f);
        mDoubleFactor = 2 * mFactor;
        a.recycle();
      }
      @Override 
      public float getInterpolation(float input) {
         if (mFactor == 1.0f) {
             return input * input;  
          } else {
              return (float)Math.pow(input, mDoubleFactor);
          } 
      }
}

加速的快慢度由參數(shù)fractor決定羡鸥。
當fractor值為1.0f時蔑穴,動畫加速軌跡相當于一條y=x^2的拋物線。如下圖:


當fractor不為1時惧浴,軌跡曲線是y=x^(2*fractor)(0<x<=1)的曲線存和。
示例:當fractor為4時,插值器的加速軌跡曲線如下圖:

如果你在使用AccelerateInterpolator時衷旅,想要那種一開始很慢捐腿,然后突然就很快的加速的動畫效果的話。
就將fractor設置大點柿顶。
你可以到這里調(diào)試下你想要的拋物線效果:http://www.wolframalpha.com/input/?i=x%5E%282*3%29%280%3Cx%3C%3D1%29

Android提供的一個不同factor的加速插值器:
(1)accelerate_cubic, factor為1.5

xml 文件定義Animator

大家應該都在xml 文件定義過 幀動畫 和 補間動畫茄袖。今天,我們就在xml中定義屬性動畫嘁锯,來看看有什么區(qū)別宪祥。
先在 res 文件下創(chuàng)建 anmator 文件夾,在創(chuàng)建 res/animator/animator_set.xml 文件:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"    
    android:ordering="together">
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleX"
        android:valueFrom="1"
        android:valueTo="0.5">
    </objectAnimator>
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleY"
        android:valueFrom="1"
        android:valueTo="0.5">
    </objectAnimator>
</set>

這個文件是實現(xiàn) 同時縮放XY軸的動畫集合家乘,我們可以看到 set 標簽 動畫集合有個
android:ordering 屬性蝗羊,android:ordering 有兩個值 :together(同時執(zhí)行),sequentially (順序執(zhí)行)仁锯。接下來在代碼中加載動畫:

// 加載動畫
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.animator_set);
//設置 縮放的中心點
animView.setPivotX(0);
animView.setPivotY(0);
//顯示的調(diào)用invalidate
animView.invalidate();
anim.setTarget(animView);
anim.start();

如上肘交,將 animView 設為target 就可以了。 當然扑馁,縮放 和旋轉(zhuǎn)都可以設置中心點的,我們將縮放的中心點設置在了 (0,0)凉驻,默認都是在對象中心點腻要。如果,只想實現(xiàn)單個動畫涝登,可以在xml 中去掉 set標簽雄家。

下面是總結
今天介紹了 Property Animator 的 Evaluator 、Interpolator 和 xml 定義胀滚,我們可以跟愉快的實現(xiàn)酷炫的動畫啦趟济。當然乱投,在看了Interpolator 的文章后,還是佩服的五體投地的顷编,我們要努力戚炫,像大神看齊!
接下來媳纬,我會總結下 ** 布局動畫(Layout Animations)** 双肤,然后就是 屬性動畫實戰(zhàn)啦,233333钮惠。fighting!!!

源碼茅糜,源碼中還有我之前寫的防直播打賞禮物動畫效果。歡迎大家指教素挽!

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔑赘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子预明,更是在濱河造成了極大的恐慌缩赛,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贮庞,死亡現(xiàn)場離奇詭異峦筒,居然都是意外死亡,警方通過查閱死者的電腦和手機窗慎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門物喷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人遮斥,你說我怎么就攤上這事峦失。” “怎么了术吗?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵尉辑,是天一觀的道長。 經(jīng)常有香客問我较屿,道長隧魄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任隘蝎,我火速辦了婚禮购啄,結果婚禮上,老公的妹妹穿的比我還像新娘嘱么。我一直安慰自己狮含,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著几迄,像睡著了一般蔚龙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上映胁,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天木羹,我揣著相機與錄音,去河邊找鬼屿愚。 笑死汇跨,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的妆距。 我是一名探鬼主播穷遂,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼娱据!你這毒婦竟也來了蚪黑?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤中剩,失蹤者是張志新(化名)和其女友劉穎忌穿,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體结啼,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡掠剑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了郊愧。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朴译。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖属铁,靈堂內(nèi)的尸體忽然破棺而出眠寿,到底是詐尸還是另有隱情,我是刑警寧澤焦蘑,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布盯拱,位于F島的核電站,受9級特大地震影響例嘱,放射性物質(zhì)發(fā)生泄漏狡逢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一拼卵、第九天 我趴在偏房一處隱蔽的房頂上張望奢浑。 院中可真熱鬧,春花似錦间学、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽详羡。三九已至,卻和暖如春嘿悬,著一層夾襖步出監(jiān)牢的瞬間实柠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工善涨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窒盐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓钢拧,卻偏偏與公主長得像蟹漓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子源内,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1 背景 不能只分析源碼呀葡粒,分析的同時也要整理歸納基礎知識,剛好有人微博私信讓全面說說Android的動畫膜钓,所以今...
    未聞椛洺閱讀 2,711評論 0 10
  • Animation Animation類是所有動畫(scale嗽交、alpha、translate颂斜、rotate)的基...
    四月一號閱讀 1,921評論 0 10
  • 時常在想究竟是為什么讓我進入了汽車行業(yè)沃疮? 這是我畢業(yè)后第一份正規(guī)職業(yè)盒让,因為身體的原因,所以我選擇的是人事和行政忿磅∨幢颍可...
    小元子美眉閱讀 411評論 0 1
  • 臨近寒冬,白晝愈來愈短葱她,晚上下班撩扒,出地鐵站,臨近八點吨些,外面的世界除了寒意侵人搓谆,便是黑夜,深深的黑豪墅;燈火通明的地鐵站...
    咖啡與薔薇閱讀 260評論 0 0
  • 很久以前泉手,知道世上有個你。 讓河流接住倒影偶器,讓鮮花及時怒放斩萌,讓年華傾其所有缝裤,三十六歲的你還是畫一般的模樣。 人前你...
    青灰搖閱讀 528評論 4 4