04.Android之動畫問題

目錄介紹

  • 4.0.0.1 Android中有哪幾種類型的動畫,屬性動畫和補間動畫有何區別?補間動畫和屬性動畫經常使用的有哪些?
  • 4.0.0.2 View動畫爲什麼不能真正改變View的位置?而屬性動畫爲什麼能夠?屬性動畫是如何改變View的屬性?
  • 4.0.0.3 補間動畫是如何做用於view的,從源碼角度分析如下?爲什麼說補間動畫沒有改變View的屬性?
  • 4.0.0.6 屬性動畫插值器和估值器的做用?插值器和估值器分別是如何更改動畫的?
  • 4.0.0.7 使用動畫會出現哪些問題?動畫佔用大量內存,如何優化?使用動畫的注意事項有哪些?

好消息

  • 博客筆記大彙總【15年10月到至今】,包括Java基礎及深刻知識點,Android技術博客,Python學習筆記等等,還包括平時開發中遇到的bug彙總,固然也在工做之餘收集了大量的面試題,長期更新維護而且修正,持續完善……開源的文件是markdown格式的!同時也開源了生活博客,從12年起,積累共計500篇[近100萬字],將會陸續發表到網上,轉載請註明出處,謝謝!
  • 連接地址:https://github.com/yangchong211/YCBlogs
  • 若是以爲好,能夠star一下,謝謝!固然也歡迎提出建議,萬事起於忽微,量變引發質變!全部的筆記將會更新到GitHub上,同時保持更新,歡迎同行提出或者push不一樣的見解或者筆記!

4.0.0.1 Android中有哪幾種類型的動畫,屬性動畫和補間動畫有何區別?

  • 常見三類動畫
    • View動畫(View Animation)/補間動畫(Tween animation):對View進行平移、縮放、旋轉和透明度變化的動畫,不能真正的改變view的位置。應用如佈局動畫、Activity切換動畫
    • 逐幀動畫(Drawable Animation):是View動畫的一種,它會按照順序播放一組預先定義好的圖片
    • 屬性動畫(Property Animation):對該類對象進行動畫操做,真正改變了對象的屬性
  • 屬性動畫和補間動畫區別
    • 屬性動畫纔是真正的實現了view的移動,補間動畫對view的移動更像是在不一樣地方繪製了一個影子,實際對象仍是處於原來的地方。當動畫的repeatCount設置爲無限循環時,若是在Activity退出時沒有及時將動畫中止,屬性動畫會致使Activity 沒法釋放而致使內存泄漏,而補間動畫卻沒問題。xml文件實現的補間動畫,複用率極高。在 Activity切換,窗口彈出時等情景中有着很好的效果。
    • 補間動畫還有一個致命的缺陷,就是它只是改變了View的顯示效果而已,而不會真正去改變View的屬性。什麼意思呢?好比說,如今屏幕的左上角有一個按鈕,而後咱們經過補間動畫將它移動到了屏幕的右下角,如今你能夠去嘗試點擊一下這個按鈕,點擊事件是絕對不會觸發的,由於實際上這個按鈕仍是停留在屏幕的左上角,只不過補間動畫將這個按鈕繪製到了屏幕的右下角而已。下面這張圖摘自網絡!
    • image
  • 補間動畫和幀動畫xml文件存放的位置
    • 補間動畫是放置到res/anim/下面
    • 幀動畫是放置到res/drawable/下面,子節點爲animation-list,在這裏定義要顯示的圖片和每張圖片的顯示時長
  • 補間動畫和屬性動畫經常使用的有哪些?技術博客大總結
    • View動畫框架是舊的框架,只能用於Views。比較容易設置和能知足許多應用程序的須要。View動畫框架中一共提供了AlphaAnimation(透明度動畫)、RotateAnimation(旋轉動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(平移動畫)四種類型的補間動畫;而且View動畫框架還提供了動畫集合類(AnimationSet),經過動畫集合類(AnimationSet)能夠將多個補間動畫以組合的形式顯示出來。
    • 與屬性動畫相比View動畫存在一個缺陷,View動畫改變的只是View的顯示,而沒有改變View的響應區域,而且View動畫只能對View作四種類型的補間動畫。所以Google在Android3.0(API級別11)及其後續版本中添加了屬性動畫框架,從名稱中就能夠知道只要某個類具備屬性(即該類含有某個字段的set和get方法),那麼屬性動畫框架就能夠對該類的對象進行動畫操做(其實就是經過反射技術來獲取和執行屬性的get,set方法),一樣屬性動畫框架還提供了動畫集合類(AnimatorSet),經過動畫集合類(AnimatorSet)能夠將多個屬性動畫以組合的形式顯示出來。

4.0.0.2 View動畫爲什麼不能真正改變View的位置?而屬性動畫爲什麼能夠?屬性動畫是如何改變View的屬性?

  • View動畫爲什麼不能真正改變View的位置?而屬性動畫爲什麼能夠?
    • View動畫改變的只是View的顯示,而沒有改變View的響應區域;而屬性動畫會經過反射技術來獲取和執行屬性的get、set方法,從而改變了對象位置的屬性值。
    • Animation產生的動畫數據實際並非應用在View自己的,而是應用在RenderNode或者Canvas上的,這就是爲何Animation不會改變View的屬性的根本所在。
  • 屬性動畫是如何改變View的屬性?

4.0.0.3 補間動畫是如何做用於view的,從源碼角度分析如下?爲什麼說補間動畫沒有改變View的屬性?

  • 關於補間動畫原理
    • 要了解Android動畫是如何加載出來的,咱們首先要了解Android View 是如何組織在一塊兒的.每一個窗口是一顆View樹. RootView是DecorView,在佈局文件中聲明的佈局都是DecorView的子View.是經過setContentView來設置進入窗口內容的. 由於View的佈局就是一棵樹.因此繪製的時候也是按照樹形結構來遍歷每一個View進行繪製.ViewRoot.java中 draw函數準備好Canvas後 調用 mView.draw(canvas),這裏的mView是DecorView.
    • 下面看一下遞歸繪製的幾個步驟:技術博客大總結
    • 1.繪製背景
    • 2.若是須要,保存畫布(canvas),爲淡入淡出作準備
    • 3.經過調用View.onDraw(canvas)繪製View自己的內容
    • 4.經過 dispatchDraw(canvas)繪製本身的孩子,dispatchDraw->drawChild->child.draw(canvas) 這樣的調用過程被用來保證每一個子 View 的 draw 函數都被調用
    • 5.若是須要,繪製淡入淡出相關的內容並恢復保存的畫布所在的層(layer)
    • 6.繪製修飾的內容(例如滾動條)
    • 當一個 ChildView 要重畫時,它會調用其成員函數 invalidate() 函數將通知其 ParentView 這個 ChildView 要重畫,這個過程一直向上遍歷到 ViewRoot,當 ViewRoot 收到這個通知後就會調用上面提到的 ViewRoot 中的 draw 函數從而完成繪製。Android 動畫就是經過 ParentView 來不斷調整 ChildView 的畫布座標系來實現的
  • 如何計算補間動畫數據
    • 首先進入Animation類,而後找到getTransformation方法,主要是分析這個方法邏輯,如圖所示
      • image
    • 那麼這個方法中作了什麼呢?Animation在其getTransformation函數被調用時會計算一幀動畫數據,而上面這些屬性基本都是在計算動畫數據時有相關的做用。
    • 第一步:若startTime爲START_ON_FIRST_FRAME(值爲-1)時,將startTime設定爲curTime
    • 第二步:計算當前動畫進度:
      • normalizedTime = (curTime - (startTime + startOffset))/duration
      • 若mFillEnabled==false:將normalisedTime夾逼至[0.0f, 1.0f]
    • 第三步:判斷是否須要計算動畫數據:
      • 若normalisedTime在[0.0f, 1.0f],需計算動畫數據
      • 若normalisedTime不在[0.0f, 1.0f]:
        • normalisedTime<0.0f, 僅當mFillBefore==true時才計算動畫數據
        • normalisedTime>1.0f, 僅當mFillAfter==true時才計算動畫數據
    • 第四步:若需須要計算動畫數據:
      • 若當前爲第一幀動畫,觸發mListener.onAnimationStart
      • 若mFillEnabled==false:將normalisedTime夾逼至[0.0f, 1.0f]
      • 根據插間器mInterpolator調整動畫進度:
      • interpolatedTime = mInterpolator.getInterpolation(normalizedTime)
      • 若動畫反轉標誌位mCycleFlip爲true,則
      • interpolatedTime = 1.0 - normalizedTime
      • 調用動畫更新函數applyTransformation(interpolatedTime, transformation)計算出動畫數據
    • 第五步:若夾逼以前normalisedTime大於1.0f, 則判斷是否需繼續執行動畫:
      • 已執行次數mRepeatCount等於需執行次數mRepeated
        • 若未觸發mListener.onAnimationEnd,則觸發之
      • 已執行次數mRepeatCount不等於需執行次數mRepeated技術博客大總結
        • 自增mRepeatCount
        • 重置mStartTime爲-1
        • 若mRepeatMode爲REVERSE,則取反mCycleFlip
        • 觸發mListener.onAnimationRepeat

4.0.0.6 屬性動畫插值器和估值器的做用?插值器和估值器分別是如何更改動畫的?

  • 插值器(Interpolator):根據時間流逝的百分比計算出當前屬性值改變的百分比。肯定了動畫效果變化的模式,如勻速變化、加速變化等等。View動畫和屬性動畫都可使用。經常使用的系統內置插值器:
    • 線性插值器(LinearInterpolator):勻速動畫
    • 加速減速插值器(AccelerateDecelerateInterpolator):動畫兩頭慢中間快
    • 減速插值器(DecelerateInterpolator):動畫愈來愈慢
  • 類型估值器(TypeEvaluator):根據當前屬性改變的百分比計算出改變後的屬性值。針對於屬性動畫,View動畫不須要類型估值器。經常使用的系統內置的估值器:技術博客大總結
    • 整形估值器(IntEvaluator)
    • 浮點型估值器(FloatEvaluator)
    • Color屬性估值器(ArgbEvaluator)

4.0.0.7 使用動畫會出現哪些問題?動畫佔用大量內存,如何優化?使用動畫的注意事項有哪些?

  • 使用動畫會出現哪些問題?
    • OOM問題:這個問題主要出如今幀動畫中,當圖片數量較多且圖片較大時就極易出現OOM,這個在實際開發中要尤爲注意,儘可能避免使用幀動畫。
    • 內存泄露:在屬性動畫中有一類無限循環的動畫,這類動畫須要在Activity退出時及時中止,不然將致使Activity沒法釋放從而形成內存泄露,經過驗證後發現View動畫並不存在此問題。
  • 動畫佔用大量內存,如何優化?
  • 使用動畫的注意事項有哪些?
    • OOM問題:這個問題主要出如今幀動畫中,當圖片數量較多且圖片較大時就極易出現OOM,這個在實際開發中要尤爲注意,儘可能避免使用幀動畫。
    • 內存泄露:在屬性動畫中有一類無限循環的動畫,這類動畫須要在Activity退出時及時中止,不然將致使Activity沒法釋放從而形成內存泄露,經過驗證後發現View動畫並不存在此問題。
    • 兼容性問題:動畫在3.0如下的系統有兼容性問題,在某些特殊場景可能沒法正常工做,所以要作好適配工做。
    • View動畫的問題:View動畫是對View的影像作動畫,並非真正改變View的狀態,所以有時候會出現動畫完成後View沒法隱藏的現象,即setVisibility(View.GOEN)失效了,這個時候只要調用view.clearAnimation()清除View動畫便可解決問題。技術博客大總結
    • 不要使用px:在進行動畫的過程當中,要儘可能使用dp,使用px會致使在不用的設備上有不用的效果。
    • 動畫元素的交互:從3.0開始,將view移動(平移)後,屬性動畫的單擊事件觸發位置爲移動後的位置,可是View動畫仍然在原位置。在Android3.0之前的系統中,不論是View動畫仍是屬性動畫,新位置都沒法觸發單擊事件同時,老位置仍然能觸發單擊事件(由於屬性動畫在Android3.0之前是沒有的,是經過兼容包實現的,底層也是調用View動畫)。
    • 硬件加速:使用動畫的過程當中,建議開啓硬件加速,這樣會提升動畫的流暢性。
    • 開啓方法:
    • 在你的Android manifest文件,添加hardwareAccelerated屬性就能夠了。能夠給整個application添加,也能夠單獨給一個acitivty添加,該屬性默認值爲false;

關於其餘內容介紹

01.關於博客彙總連接

02.關於個人博客

相關文章
相關標籤/搜索