0. 原始碼地址
1. 引子
動畫效果是一個非常棒的使用者體驗,Android 加入Material Design,app賞心悅目了不少,關鍵還完全沒有增加開發者的負擔。不需要多寫哪怕一行程式碼,使用者體驗已經提升了很多。
但是在介面中動態刪除一個View,或者更新View顯示時,介面還是存在抖動的現象,過渡不夠平滑。所以是否能有一種方法對開發者透明的高效動畫實現呢?幾天前看到有個同學實現了Android-skin-support Android換膚框架,主要原理就是在執行onCreate
之前通過setFactory(LayoutInflater inflater, LayoutInflaterFactory factory)
方法替換系統View為自定義的View,從而自如切換View的一些屬性。仔細想想,利用這種方式可以實現太多的功能了。
2. 思路
其實我們需要實現的動畫主要是View在Visible,Gone
或者內容更新的時候可以平滑切換:
如圖中的第一個TextView在由text1更新到text1_change時,如果有動畫是漸隱變化的,無動畫時則比較生硬。
我們實現Animation everywhere主要就是實現Visible 、Gone、Update
動畫,其它動畫不夠通用,如果需要可以手動實現。我們採用的方式也是在setFactory(LayoutInflater inflater, LayoutInflaterFactory factory)
方法中替換系統View,這樣可以保證對開發透明,不需要在佈局檔案中作出改動。
自定義View主要是修改View自身的setVisibility()
和更新內容的一些方法,如TextView 的setText()
的方法。
3. 存在的問題
替換原生View是一個比較有風險的事情,因此應該提供選項,某些Activity中選擇原生View,在有需求的地方再選擇Animator View。
同時,由於並不是所有時候都需要動畫,如首次載入介面的時候,如果每個View都執行一次動畫,不僅耗費資源,也很奇怪。因此需要提供開啟動畫和關閉動畫的選項,在需要的時候開啟動畫。
4. 程式碼實現
4.1 功能概要
- 自定義View,覆蓋原生
setVisibility()
等方法 - 實現多種Animator
- 實現配置View可用動畫的架構
4.2 細節實現
自定義View
覆蓋setVisibility
方法:@Override public void setVisibility(int visibility) { if (AnimatorManager.getConfig().getTextViewVisibleAnimationType() == ViewAnimatorType.None) { super.setVisibility(visibility); } else { this.visibleStatus = visibility; if (visibility == GONE) { ViewAnimatorUtil.executeAnimator(this, AnimatorManager.getConfig().getTextViewVisibleAnimationType(), visibleAction); } else { visibleAction.action(); } } }複製程式碼
主要是判斷如果不執行動畫,那麼執行父類方法即可。
實現多種Animator
這個主要實現三類動畫,出現、消失、更新,可以放置在不同的資料夾中。這裡使用了Enum值表示不同的動畫,方便配置使用:
ROTATE3{
@Override
public void apply(View view, Action action) {
SkinRotateAnimator3.getInstance().apply(view, action).start();
}
},複製程式碼
- 實現配置View可用動畫的架構
這個主要通過兩個類來實現,一個提供動畫操作介面,一個提供動畫配置介面:
動畫配置使用build的方式,操作方法:
new AnimatorConfig.Builder()
.textviewTextAnimationType(ViewAnimatorType.AlphaUpdateAnimator)
.textviewVisibleAnimationType(ViewAnimatorType.TranslationAlphaHideAnimator)
.imageviewVisibleAnimationType(ViewAnimatorType.TranslationAlphaHideAnimator)
.build())複製程式碼
以上就是實現animator everywhere 的思路和基本的程式碼結構,原始碼可以參考AndroidSkinAnimator
以下是已經實現的一些動畫:
4.3 框架使用:
1.繼承
SkinCompatActivity
, 同時支援了換膚功能2.如果Activity需要支援全域性動畫,覆蓋方法:
@Override
protected boolean needAnimator() {
return true;
}複製程式碼
如果不需要,則不用理會
- 3.在Activity中設定動畫配置:
setAnimatorConfig(new AnimatorConfig
.Builder()
.textviewTextAnimationType(ViewAnimatorType.AlphaUpdateAnimator)
.textviewVisibleAnimationType(ViewAnimatorType.TranslationAlphaHideAnimator)
.build());複製程式碼
在其它地方設定配置:
AnimatorManager.setConfig(new AnimatorConfig.Builder()
.textviewVisibleAnimationType(ViewAnimatorType.TranslationAlphaHideAnimator)
.textviewTextAnimationType(ViewAnimatorType.AlphaUpdateAnimator)
.build());複製程式碼
- 4.在需要的地方打個關閉動畫:
AnimatorManager.openAnimator();
AnimatorManager.closeAnimator();複製程式碼
5. 換膚動畫
感覺動畫寫起來還是挺好玩的,於是對換膚過程也寫了幾個動畫:
其實實現起來都比較簡單,主要就是把動畫進行分解,通過組合使用平移、旋轉、大小變化等基本動畫,就可以做出比較好動畫。
歡迎關注公眾號wutongke,每天推送移動開發前沿技術文章:
推薦閱讀: