Android Animation 系列——屬性動畫(Property Animation)

000 屬性動畫簡介

屬性動畫是 Android API level 11(Android 3.0)中添加的動畫框架,功能強大,擴展性強。介紹屬性動畫,就須要說明三個問題:java

屬性是什麼?git

用官方的話說,Property is a field in an object。更進一步解釋,這裏的屬性是指一個對象中具備 setter/getter 方法的變量。github

屬性動畫能夠作什麼?網絡

通常來講,動畫是一種視覺效果,可是屬性動畫的內容要更普遍,除了作一些視覺效果以外,屬性動畫還能夠用相似動畫的方式默默改變一些數據。固然,最主要的仍是實現視覺效果,包括常見的透明度、縮放、平移、旋轉效果,也能夠擴展出其餘的屬性(好比顏色)。框架

與以前的 View Animation 有什麼區別?ide

View Animation 是在 API level 1 開始支持的動畫框架,內容只有基本的透明度、縮放、平移、旋轉,且動畫的對象只能是 View。工具

兩者的區別有如下幾點:動畫

  1. 屬性動畫實際改變了動畫目標的屬性值,好比平移一個 View,View 的位置真實發生了改變,而 View Animation僅是改變了屏幕繪製位置,真實位置不變。
  2. 屬性動畫能夠做用於沒有繪製到屏幕上的對象。
  3. 屬性動畫能夠做用於非 View 對象,也能夠製做四類基本動畫以外的動畫效果。
  4. View Animation 的代碼量更少,效率更高。

001 相關API說明

屬性動畫中新添加的類主要是這些: lua

property animation framework.jpg

Animator

做爲屬性動畫的基類,Animator 提供了動畫最基本的屬性。spa

僅列出一部分(我以爲)經常使用的。

Method Name Function
start() 開始播放
cancel() 取消動畫
isRunning() 是否正在播放
addListener 添加監聽回調
setTarget 設置動畫目標Object
setDuration 設置播放時長,單位:毫秒
setInterpolator 設置插值器

關於插值器的內容本文暫不介紹了。

ValueAnimator

構造方法

//直接建立
    ValueAnimator valueAnimator = new ValueAnimator();
//帶參數建立
    ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 2.0f);
    // ValueAnimator valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), Color.RED, Color.GREEN);
    // ...還有ofArgb,ofInt,ofPropertyValuesHolder
複製代碼

比起 Animator 增長的一些經常使用方法

Method Name Function
setStartDelay 設置動畫啓動延遲,單位:毫秒
addUpdateListener 添加Value更新的監聽回調
setRepeatMode 設置重複播放模式,RESTART或REVERSE
setRepeatCount 設置重複播放次數
ObjectAnimtor

構造方法

//直接建立
    ObjectAnimator objectAnimator = new ObjectAnimator();
//帶參數建立
    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mView, "alpha", 1.0f, 0.7f);
    //...相似的構造方法有不少,就是參數不一樣,這些參數均可以經過setter方法設置。
複製代碼

ObjectAnimatior 增長了屬性動畫最基本的方法——設置屬性。

Method Name Function
setProperty 設置動畫目標屬性
setPropertyName 經過name設置動畫目標屬性
setIntValues(int... values) 設置一系列動畫參數,按順序執行
setFloatValues(float... values) 設置一系列動畫參數,按順序執行
setObjectValues(Object... values) 設置一系列動畫參數,按順序執行
AnimatorSet

AnimatorSet 的功能就是把多個各類 Animator 對象整合成一個動畫,有點相似與 ViewGroup。

Method Name Function
playTogether 多個動畫一塊兒播放
playSequentially 多個動畫順序播放

010 使用場景分析

Animator對象

ValueAnimator 的功能很單一,比較像「時間軸」,就是設置一個值,在一段時間內以某種規則變化。這也是 ObjectAnimator 實現動畫的基礎。

舉個例子,經過 VlaueAnimator 改變 View 的顏色:

private int mColor = Color.RED;
    public ValueAnimator valueAnimator;
//...
//...
    valueAnimator = ValueAnimator.ofObject(new ArgbEvaluator(), mColor, Color.rgb(0,0,255));
    valueAnimator.setDuration(3000);
    valueAnimator.setInterpolator(new LinearInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mColor = (int) animation.getAnimatedValue();
            }
        });
複製代碼

onAnimationUpdate 方法中把變化後的顏色刷新到 UI 界面就好了。效果是這樣的:

ValueAnimator sample.gif

相比之下 ObjectAnimator 纔是屬性動畫中的主角,建立 ObjectAnimator 對象實現動畫須要有幾個要素:

  1. propertyName:要變化的屬性名(String)
  2. target:具備該屬性的 Object 對象
  3. values:對應屬性的變化值,數據類型要和屬性的類型一致

屬性名接受一個 String 類型的參數,就很容易出錯。能夠經過輸入 target 的 object 對象,在代碼提示中找 setter 方法來肯定屬性名。View 的屬性名是比較經常使用的,好比:alpharotationscaleXscaleYtranslationXtranslationYrotationXrotationY等。

舉個例子,網絡加載中可能會大量用到的一種loading動畫。

ObjectAnimator animator = new ObjectAnimator();
    animator.setPropertyName("rotation");
    animator.setTarget(ivLoading);
    animator.setFloatValues(0,360);
    animator.setDuration(900);
    animator.setRepeatMode(ObjectAnimator.RESTART);
    animator.setRepeatCount(ObjectAnimator.INFINITE);
    animator.setInterpolator(new LinearInterpolator());
    animator.start();
複製代碼

代碼含義比較清晰,須要注意的是setInterpolator默認的插值器並非線性的,下面給出兩種效果,左側是 LinearInterpolator ,右側是默認的。

ObjectAnimatior Sample.gif

xml實現

xml 實現動畫是一種比較合理的複用動畫方式,能夠有效避免在 Controller 層寫過多隻屬於 View 層的代碼。

屬性動畫的 xml 文件須要放在res/animator文件夾下。

語法與 View Animation 差異比較大,大概是這樣子的:

xml animator(官方文檔截圖).png

直觀感覺就是比 View Animation 的 xml 實現麻煩不少,實際上因爲 xml 文件的限制兩者功能上差很少,應該是 View Animation 更加經常使用一點。(我的感覺)

view.animate()

ObjectAnimator 的代碼寫起來不怎麼好看,由於老是在 objectAnimator.xxx(),比起單獨在Activity中實現某些交互效果,把簡單而經常使用的動畫效果封裝成工具類會更理想一些。可是交互效果是變幻無窮的,總有一些獨特的動畫沒法複用。

因而在 API level 12 中,出現了針對 View 的屬性動畫 ViewPropertyAnimtor。ViewProperty 中封裝了 View 相關的經常使用動畫參數的設置以及多種回調,並用 ObjectAnimator 實現了動畫效果,對外提供了至關簡單易懂的流式 API,使動畫的代碼也能夠寫的很爽。

使用方法:

  1. 獲取 ViewPropertyAnimator 對象

ViewPropertyAnimator 沒有 public 的構造方法,只能經過 View 對象的 animate() 方法得到。使用的 View 對象就是動畫的 target。

ViewPropertyAnimator 對象是會重複使用的,屢次調用'animate()'只會建立一個 ViewPropertyAnimator。

  1. 設置動畫參數

相關的 API 名稱都很明確,就不一一介紹效果了

ViewPropertyAnimator API.png

ViewPropertyAnimator API.png

  1. 設置回調(可選)

就是setListener方法。其實全部的動畫均可以設置 Listener ,只是在 ViewPropertyAnimator 中更加劇要,由於從 API 能夠看出每一種動畫只能傳入一個參數,若是須要同一種動畫多段執行,就只能經過監聽動畫結束脩改參數值再開始動畫。

setListener 方法接收一個 Animator.AnimatorListener 接口的實例,能夠直接建立 Animator.AnimatorListener 實例實現全部方法,也能夠建立 AnimatorListenerAdapter 只重寫須要的方法。

ViewPropertyAnimator 的複用一樣會影響 Listener,若是是同一個 View 的多個動畫且不相關,須要在不須要 Listener 的動畫中調用setListener(null)

這裏也應該舉個例子,不過沒什麼好的想法,姑且再寫一遍 loading 動畫,就當對比一下兩種 API 格式吧。(kotlin代碼,對比一下設置動畫的 API 就行了)

ivLoadingRight.setOnClickListener {
    ivLoadingRight.animate()
            .rotationBy(360f)
            .setDuration(800)
              .setInterpolator(LinearInterpolator())
            .setListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator?) {
                    super.onAnimationEnd(animation)
                    ivLoadingRight.animate()
                            .rotationBy(360f)
                            .setDuration(800)
                              .setInterpolator(LinearInterpolator())
                            .start()
                }
            }).start()
複製代碼

011 結語

由於我並無作過太多的動畫效果,剛開始寫的時候只想總結一下各類方法的用法和效果,然而那樣就會不能避免的翻譯官方文檔,且內容雜亂,不易整理 demo。因而先寫了一些簡單的動畫效果,依據實際代碼反向整理了這篇文章。

文中 gif 圖對應代碼都在示例工程(AnimatorSample)中,地址:https://github.com/xhd-Git/Samples

相關文章
相關標籤/搜索