Android 動畫框架實現

劉強東發表於2018-05-30

這裡我說是指的Google對於常用的動畫效果進行的封裝. 有很多炫酷的效果可以通過這些封裝快速實現.

LayoutAnimationController

用於支援列表控制元件(RecyclerView和ListView)的Item動畫效果

屬性: Android 動畫框架實現

  1. 動畫

    傳入動畫XML檔案來決定載入動畫

  2. 動畫順序

    有三個值: normal 按照正常順序 reverse 從最後的控制元件開始載入動畫 random 隨機順序

  3. 延遲時間

    毫秒值單位, 表示每個條目的載入時間相差多少毫秒

  4. 動畫插值器

佈局動畫使用方式有兩種:

  1. 佈局中引用動畫

在anim目錄下建立XML

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/animation_set"
    android:animationOrder="normal"
    android:delay="300">
</layoutAnimation>
複製程式碼

在佈局XML中引用XML動畫

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    android:id="@+id/ll_root"
    android:gravity="center"
    android:layoutAnimation="@anim/animation_layout"
    >
複製程式碼
  1. 程式碼中引用動畫
//通過載入XML動畫設定檔案來建立一個Animation物件;
Animation animation=AnimationUtils.loadAnimation(this, R.anim.list_anim);
//得到一個LayoutAnimationController物件;
LayoutAnimationController mLayoutAnimationController = new LayoutAnimationController(animation);
//設定控制元件顯示的順序;
mLayoutAnimationController.setOrder(LayoutAnimationController.ORDER_REVERSE);
//設定控制元件顯示間隔時間;
mLayoutAnimationController.setDelay(1);
//為ListView設定LayoutAnimationController屬性;
mList.setLayoutAnimation(mLayoutAnimationController);
複製程式碼

Tip: 注意佈局動畫要麼在onCreate方法中執行, 如果在其他地方執行就需要你手動執行佈局物件的invalidate()方法.

該函式屬於ViewGroup下的動畫效果

void setLayoutAnimation (LayoutAnimationController controller)
複製程式碼

LayoutTransitionController

參考網上寫法我出現了Crash情況. 並且無法直接執行ExampleDemo. 指向ObjectAnimator的View引數不能為Null, 報空指標異常. 我沒有解決故也不做講解.

不過通過在XML佈局中給ViewGroup新增如下屬性可以啟用預設的動畫效果

android:animateLayoutChanges="true"
複製程式碼

ViewAnimationUtils

揭示效果也可以看做是控制一個控制元件的圓角變化動畫效果. ViewAnimationUtils這個類只有一個方法:

Animator createCircularReveal (View view, 
                int centerX, 
                int centerY, 
                float startRadius, 
                float endRadius)
複製程式碼
Android 動畫框架實現
// 建立環形顯示動畫
Animator animator = ViewAnimationUtils.createCircularReveal(mBtnExtract, mBtnExtract.getWidth() / 2, mBtnExtract.getHeight() / 2, mBtnExtract.getWidth() / 4, mBtnExtract.getHeight() / 4);

animator.setInterpolator(new LinearInterpolator());
animator.setDuration(1000);
animator.start();
複製程式碼

overridePendingTransition

自定義進入下一個Activity和退出當前Activity的動畫XML檔案, 不需要考慮相容問題.

注意一定要在startActivity或者finishd的後面呼叫才有效.

overridePendingTransition(int enterAnim, int exitAnim); // 0表示不顯示動畫
複製程式碼
  • enterAnim 介面進入動畫
  • exitAnim 介面退出動畫

ViewPropertyAnimator

檢視類View提供一個animate()方法方便快速的設定常用動畫

ViewPropertyAnimator animate ()
複製程式碼

ViewPropertyAnimator這個類基本上可以設定View的所有屬性, 方法看名字就可以全部理解了

其中很多方法有帶"By"和不帶的同名方法. 帶"By"相當於相對屬性值, 不帶就是絕對屬性值.

ViewPropertyAnimator translationX (float value)
ViewPropertyAnimator translationXBy (float value)
複製程式碼

Tip: 如果使用鏈式呼叫可以同時執行多個動畫效果.

view.animate()  
        .scaleX(1)
        .scaleY(1)
        .alpha(1);
複製程式碼

監聽器

ViewPropertyAnimator setListener (Animator.AnimatorListener listener)
複製程式碼

AnimatorListener包含四種回撥

// 在動畫被取消的時候
abstract void	onAnimationCancel(Animator animation)

// 無論動畫是否取消, 結束的時候都會回撥
abstract void	onAnimationEnd(Animator animation)

default void	onAnimationEnd(Animator animation, 
                               boolean isReverse) // 是否重複

// 動畫重複的時候回撥
abstract void	onAnimationRepeat(Animator animation) 

// 動畫開始
abstract void	onAnimationStart(Animator animation)

default void	onAnimationStart(Animator animation, 
                                 boolean isReverse) // 動畫是否重複
複製程式碼

還有一種一次性的回撥, 如果ViewPropertyAnimator物件再次執行動畫並不會回撥. 並且withEndAction()在動畫被取消的時候不會回撥. 這和onAnimationEnd()不同.

ViewPropertyAnimator withEndAction (Runnable runnable)

ViewPropertyAnimator withStartAction (Runnable runnable)
複製程式碼

更新

該回撥會在大概每10毫秒執行一次

ViewPropertyAnimator setUpdateListener (ValueAnimator.AnimatorUpdateListener listener)
複製程式碼

DynamicAnimation

DynamicAnimation是在API25出現的基於物理運動效果的動畫, 屬於抽象類. 官方目前只有SpringAnimation繼承該類. 使用SpringAnimation的好處是讓動畫顯得不那麼生硬, 可能有人會說動畫插值器也可以. 但是鑑於動畫插值器涉及到座標軸演算法Google為了讓更多人能夠方便的優化自己的動畫效果才出現了DynamicAnimation.

官方說明

Android 動畫框架實現

以下介紹官方示例


SpringForce spring = new SpringForce(0)
  .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
  .setStiffness(SpringForce.STIFFNESS_LOW);

final SpringAnimation anim = new SpringAnimation(mImag, DynamicAnimation.SCALE_Y)
  .setMinValue(0).setSpring(spring).setStartValue(1);
anim.start();
複製程式碼

SpringForce

通過SpringAnimation的方法設定

SpringAnimation setSpring (SpringForce force)
複製程式碼

或者不建立SpringForce直接通過SpringAnimation得到一個SpringForce例項也可以

SpringForce getSpring ()
複製程式碼

是控制SpringAnimation的力度, 分別控制三種彈性特性

  • 阻尼比例
  • 僵硬程度

建立構造方法

SpringForce (float finalPosition) //  最終位置
複製程式碼

SpringForce可以決定動畫的最終值卻無法決定起始值(預設起始值是當前屬性值), 起始值也可以由SpringAnimation設定.

阻尼比例設定(阻尼具體提現在擺動次數)

SpringForce setDampingRatio (float dampingRatio)
複製程式碼

SpringForce內部提供四種阻尼比例:

public static final float DAMPING_RATIO_HIGH_BOUNCY = 0.2f;  
 
public static final float DAMPING_RATIO_MEDIUM_BOUNCY = 0.5f; // 預設值
 
public static final float DAMPING_RATIO_LOW_BOUNCY = 0.75f; 
 
public static final float DAMPING_RATIO_NO_BOUNCY = 1f;
複製程式碼

僵硬值具體提現在擺動時間上

SpringForce setStiffness (float stiffness)
複製程式碼

同樣SpringForce也提供了四種僵硬值:

public static final float STIFFNESS_HIGH = 10_000f;
 
public static final float STIFFNESS_MEDIUM = 1500f; // 預設值
 
public static final float STIFFNESS_LOW = 200f;
 
public static final float STIFFNESS_VERY_LOW = 50f;
複製程式碼

Spring的構造方法

SpringAnimation (View v,  // 目標檢視
                DynamicAnimation.ViewProperty property) // 屬性值, 後面將重點講解

SpringAnimation (View v, 
                DynamicAnimation.ViewProperty property, 
                float finalPosition)
複製程式碼

ViewProperty是內部的一個抽象類

Android 動畫框架實現

從原始碼可以看出主要作用就是設定屬性值

DynamicAnimation提供一系列預設的ViewProperty

TRANSLATION_X
TRANSLATION_Y
TRANSLATION_Z
SCALE_X
SCALE_Y
ROTATION
ROTATION_X
ROTATION_Y
X
Y
Z
ALPHA
SCROLL_X
SCROLL_Y
複製程式碼

SpringAnimation在運動時候也可以修改最終位置

void animateToFinalPosition (float finalPosition)
複製程式碼

AnimatedStateListDrawable

注意和StateListAnimator有所區分, 限制api21;

StateListAnimator 即 <selector>標籤中的item從Drawable換成了animation

<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
 
    <item
        android:id="@+id/on"
        android:state_activated="true">
        <bitmap
            android:src="@drawable/ic_heart_100"/>
    </item>
 
    <item
        android:id="@+id/off">
        <bitmap
            android:src="@drawable/ic_heart_0"/>
    </item>
 
    <transition
        android:fromId="@+id/on"
        android:toId="@+id/off"
        android:drawable="@drawable/animation_emptying">
    </transition>
 
    <transition
        android:fromId="@id/off"
        android:toId="@id/on"
        android:drawable="@drawable/animation_filling">
    </transition>
 
</animated-selector>
複製程式碼

item可以指定起始和結束的點陣圖以及觸發狀態

transition可以指定當觸發狀態時執行什麼動畫

更多動畫閱讀我的其他文章

  • 向量動畫
  • 轉場動畫
  • ViewAnimator

相關文章