Android開發(fā)藝術(shù)探索 第7章 動畫深入分析 讀書筆記

Android動畫可以分3種:View動畫,幀動畫和屬性動畫;屬性動畫為API11的新特性,在低版本是無法直接使用屬性動畫的。
本章主要學(xué)習(xí)內(nèi)容:

  1. View動畫以及自定義View動畫。
  2. View動畫的一些特殊使用場景。
  3. 對屬性動畫做了一個(gè)全面的介紹。
  4. 使用動畫的一些注意事項(xiàng)。

7.1 View動畫

  1. View動畫的四種變換效果對應(yīng)著Animation的四個(gè)子類:TranslateAnimation(平移動畫)、ScaleAnimation(縮放動畫)、RotateAnimation(旋轉(zhuǎn)動畫)和AlphaAnimation(透明度動畫),他們即可以用代碼來動態(tài)創(chuàng)建也可以用XML來定義,推薦使用可讀性更好的XML來定義。
  2. <set>標(biāo)簽表示動畫集合,對應(yīng)AnimationSet類,它可以包含若干個(gè)動畫,并且他的內(nèi)部也可以嵌套其他動畫集合。android:interpolator 表示動畫集合所采用的插值器,插值器影響動畫速度,比如非勻速動畫就需要通過插值器來控制動畫的播放過程。
    android:shareInterpolator表示集合中的動畫是否和集合共享同一個(gè)插值器,如果集合不指定插值器,那么子動畫就需要單獨(dú)指定所需的插值器或默認(rèn)值。
  3. Animation通過setAnimationListener方法可以給View動畫添加過程監(jiān)聽。
  4. 自定義View動畫只需要繼承Animation這個(gè)抽象類,并重寫initialize和applyTransformation方法,在initialize方法中做一些初始化工作,在applyTransformation中進(jìn)行相應(yīng)的矩形變換,很多時(shí)候需要采用Camera來簡化矩形變換過程。
  5. 幀動畫是順序播放一組預(yù)先定義好的圖片,類似電影播放;使用簡單但容易引發(fā)OOM,盡量避免使用過多尺寸較大的圖片。

7.2 View動畫的特殊使用場景

  1. LayoutAnimation作用于ViewGroup,為ViewGroup指定一個(gè)動畫,當(dāng)他的子元素出場的時(shí)候都會具有這種動畫,ListView上用的多,LayoutAnimation也是一個(gè)View動畫。
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animationOrder="normal"
    android:delay="0.3" android:animation="@anim/anim_item"/>
//--- delay 表示動畫開始的時(shí)間延遲,比如子元素入場動畫的時(shí)間周期為300ms,
//那么0.5表示每個(gè)子元素都需要延遲150ms才開始播放入場動畫。
//--- animationOrder 表示子元素的動畫的順序,有三種選項(xiàng):
//normal(順序顯示)、reverse(逆序顯示)和random(隨機(jī)顯示)。
//---1. android:animation 為子元素指定具體的入場動畫
//----------------------
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:shareInterpolator="true">
    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />
    <translate
        android:fromXDelta="300"
        android:toXDelta="0" />
</set>

使用LayoutAnimation

//--- 第一種方法、為需要的ViewGroup指定android:layoutAnimation屬性
//---這樣ViewGroup的子View就有出場動畫了
   <ListView
       android:id="@+id/lv"
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:layoutAnimation="@anim/anim_layout"/>
//
//--- 第二種方法、通過LayoutAnimationController來實(shí)現(xiàn)
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listview.setLayoutAnimation(controller);
  1. Activity/Fragment的切換效果
    在startActivity(Intent)或finish()之后調(diào)用overridePendingTransition(int enterAnim,int exitAnim)方法。
    Fragment也可以添加切換動畫,通過FragmentTransaction中的
    setCustomAnimations()方法來添加;需考慮兼容性使用View動畫,屬性動畫是API11新引入的;

7.3屬性動畫

  1. 屬性動畫可以對任意對象的屬性進(jìn)行動畫而不僅僅是View,動畫默認(rèn)間隔300ms,默認(rèn)幀率10ms/幀。在一個(gè)時(shí)間間隔內(nèi)完成對象從一個(gè)屬性值到另一個(gè)屬性值的改變。
  2. android:propertyName 表示屬性動畫的作用的屬性的名稱 。
    android:duration 表示動畫的時(shí)長。
    android:valueFrom 表示動畫的起始值。
    android:valueTo 表示屬性的結(jié)束值。
    android:startOffset 表示動畫的延遲時(shí)間,當(dāng)動畫開始后,需要延遲多少毫秒才會真正播放此動畫。
    android:repeatCount 表示動畫的重復(fù)次數(shù)(默認(rèn)為0,其中-1表示無線循環(huán))。
    android:repeatMode 表示動畫的重復(fù)模式 (repeat和reverse可選,表示連續(xù)重復(fù)和逆向重復(fù)(第一次播放完之后,第二次倒著播,第三次重頭開始播,第四次倒著播))。
    android:valueType 表示android:propertyName所指定的屬性的類型,可選intType/floatType;
    如果android:propertyName指定的屬性表示顏色,則不需要指定該屬性。
  3. 實(shí)際開發(fā)中建議使用代碼來實(shí)現(xiàn)屬性動畫,代碼來實(shí)現(xiàn)比較簡單,而且很多時(shí)候一個(gè)熟悉的初始值無法提前知道,需在代碼中動態(tài)獲取。
7.3.2 理解插值器和估值器
  1. 時(shí)間插值器(TimeInterpolator)的作用是根據(jù)時(shí)間流逝的百分比來計(jì)算出當(dāng)前屬性值改變的百分比,系統(tǒng)預(yù)置的有LinearInterpolator(線性插值器:勻速動畫),AccelerateDecelerateInterpolator(加速減速插值器:動畫兩頭慢中間快),DecelerateInterpolator(減速插值器:動畫越來越慢)。
  2. 估值器(TypeEvaluator)的作用是根據(jù)當(dāng)前屬性改變的百分比來計(jì)算改變后的屬性值。系統(tǒng)預(yù)置有IntEvaluator 、FloatEvaluator 、ArgbEvaluator。
//整形估值器源碼
 /**
    * @param fraction   表示開始和結(jié)束值之間的比例
    * @param startValue  開始值         
    * @param endValue  結(jié)束值
    * @return  
    */
public class IntEvaluator implements TypeEvaluator<Integer> {
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}
  1. 插值器和估值器除了系統(tǒng)提供之外,我們還可以自定義。自定義插值器需要實(shí)現(xiàn)Interpolator或者TimeInterpolator;自定義估值器算法需要實(shí)現(xiàn)TypeEvaluator。
7.3.3屬性動畫的監(jiān)聽器
public static interface AnimatorListener {
    void onAnimationStart(Animator animation); //動畫開始
    void onAnimationEnd(Animator animation); //動畫結(jié)束
    void onAnimationCancel(Animator animation); //動畫取消
    void onAnimationRepeat(Animator animation); //動畫重復(fù)播放
}
  1. 為了方便開發(fā),系統(tǒng)提供了AnimatorListenerAdapter類,它是AnimatorListener的適配器類,可以有選擇的實(shí)現(xiàn)以上4個(gè)方法。
  2. AnimatorUpdateListener會監(jiān)聽整個(gè)動畫的過程,動畫由許多幀組成的,每播放一幀,onAnimationUpdate就會調(diào)用一次。
7.3.4 對任意屬性做動畫
  1. 屬性動畫要求作用的對象提供該屬性的get和set方法,缺一不可。
  2. 如果你的對象沒有對應(yīng)的get和set方法
  • 請給你的對象加上get和set方法,如果你有權(quán)限的話(如果直接使用系統(tǒng)的類,是無法加上的);
  • 用一個(gè)類來包裝原始對象,間接為其提供get和set方法;
//包裝View類 用于給屬性動畫調(diào)用 從而包裝了set get
public class ViewWrapper {
      private View target;
      public ViewWrapper(View target) {
          this.target = target;
      }
      public int getWidth() {
          return target.getLayoutParams().width;
      }
      public void setWidth(int width) {
          target.getLayoutParams().width = width;
          target.requestLayout();
      }
}
  • 采用ValueAnimator,監(jiān)聽動畫過程,自己實(shí)現(xiàn)屬性的改變;
   /** 使用ValueAnimator 監(jiān)聽動畫過程 自己實(shí)現(xiàn)屬性改變
     *
     * @param target 作用的View
     * @param start 動畫起始值
     * @param end 動畫終止值
     */
    private void startValueAnimator(final View target, final int start, final int end) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            private IntEvaluator mEvaluation = new IntEvaluator();//新建一個(gè)整形估值起 方便估值使用

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //獲得當(dāng)前動畫的進(jìn)度值 1~100之間
                int currentValue = (int) animation.getAnimatedValue();
                Log.e("Anim", "currentValue: " + currentValue);
                //獲得當(dāng)前進(jìn)度占整個(gè)動畫過程的比例,浮點(diǎn)型,0~1之間
                float fraction = animation.getAnimatedFraction();
                //調(diào)用估值器,通過比例計(jì)算出寬度 ,再設(shè)置給Button
                int targetWidth = mEvaluation.evaluate(fraction, start, end);
                target.getLayoutParams().width = targetWidth;
                target.requestLayout();
            }
        });
    }

7.3.5 屬性動畫的工作原理

通過反射調(diào)用get/set方法;屬性動畫需要運(yùn)行在有Looper的線程中。


7.4 使用動畫的注意事項(xiàng)

  1. 使用幀動畫時(shí),當(dāng)圖片數(shù)量較多且圖片分辨率較大的時(shí)候容易出現(xiàn)OOM,需注意,盡量避免使用幀動畫。
  2. 使用無限循環(huán)的屬性動畫時(shí),在Activity退出時(shí)及時(shí)停止,否則將導(dǎo)致Activity無法釋放從而造成內(nèi)存泄露
  3. View動畫是對View的影像做動畫,并不是真正的改變了View的狀態(tài),因此有時(shí)候會出現(xiàn)動畫完成后View無法隱藏(setVisibility(View.GONE)失效),這時(shí)候調(diào)用view.clearAnimation()清理View動畫即可解決。
  4. 不要使用px,使用px會導(dǎo)致不同設(shè)備上有不同的效果。
  5. View動畫是對View的影像做動畫,View的真實(shí)位置沒有變動,也就導(dǎo)致點(diǎn)擊View動畫后的位置觸摸事件不會響應(yīng),屬性動畫不存在這個(gè)問題。
  6. 使用動畫的過程中,使用硬件加速可以提高動畫的流暢度。
  7. 動畫在3.0以下的系統(tǒng)存在兼容性問題,特殊場景可能無法正常工作,需做好適配工作。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,460評論 6 538
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,067評論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,467評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,468評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,184評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,582評論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,616評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,794評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,343評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,096評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,291評論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,863評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,513評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,941評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,190評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,026評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,253評論 2 375

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

  • 1 背景 不能只分析源碼呀,分析的同時(shí)也要整理歸納基礎(chǔ)知識,剛好有人微博私信讓全面說說Android的動畫,所以今...
    未聞椛洺閱讀 2,735評論 0 10
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,692評論 25 708
  • 提及農(nóng)村,在我們的第一印象中是這樣的 孩子的重點(diǎn)在玩和幫父母干家務(wù) 他們的快樂很簡單,父母很多時(shí)間是在外打工,他們...
    冷_9825閱讀 416評論 2 1
  • “安生啊,你說這村口的王大媽都等了她男人三年了她男人也沒回來,我看啊,她男人怕是回不來咯。” 安生揚(yáng)了揚(yáng)眉頭,但是...
    導(dǎo)演i求平臺閱讀 138評論 0 0
  • 若苦能訴 尚還可撐 若難能助 尚還可解 一個(gè)人 獨(dú)當(dāng)一面 遠(yuǎn)在天涯 從最初的無措 到現(xiàn)今的自如 中間滋味 唯有自知 好在
    負(fù)零小子閱讀 149評論 0 0