Android SVG和Lottie庫播放動畫(Json)

Android SVG和Lottie庫播放動畫(Json)

AE-----→Json
安卓調用.json文件

一、SVG

SVG是Android 5.0中新加入的一個新特性。

從5.0開始android也開始支持SVG圖了,這使得我們可以實現更多的好看的動畫。

什麼是SVG?

SVG的全稱是Scalable Vector Graphics,叫可縮放矢量圖形。它和位圖(Bitmap)相對,SVG不會像位圖一樣因爲縮放而讓圖片質量下降。下面這個圖片展示了SVG和位圖的區別,左邊的位圖在放大後出現了鋸齒,而右邊的SVG任然清晰。

爲什麼要使用SVG

  1. SVG 可被非常多的工具讀取和修改(比如記事本),由於使用xml格式定義,所以可以直接被當作文本文件打開,看裏面的數據;
  2. SVG 與 JPEG 和 GIF 圖像比起來,尺寸更小,且可壓縮性更強,SVG 圖就相當於保存了關鍵的數據點,比如要顯示一個圓,需要知道圓心和半徑,那麼SVG 就只保存圓心座標和半徑數據,而平常我們用的位圖都是以像素點的形式根據圖片大小保存對應個數的像素點,因而SVG尺寸更小;
  3. SVG 是可伸縮的,平常使用的位圖拉伸會發虛,壓縮會變形,而SVG格式圖片保存數據進行運算展示,不管多大多少,可以不失真顯示;
  4. SVG 圖像可在任何的分辨率下被高質量地打印;
  5. SVG 可在圖像質量不下降的情況下被放大;
  6. SVG 圖像中的文本是可選的,同時也是可搜索的(很適合製作地圖);
  7. SVG 可以與 Java 技術一起運行;
  8. SVG 是開放的標準;
  9. SVG 文件是純粹的 XML;

使用SVG

  1. 可以用SVG圖片直接轉換成Android可用格式。

    我們可以通過上面的變動手動把普通SVG轉成android用的VectorDrawable,或者我們可以用這個網站自動完成轉換 http://inloop.github.io/svg2android/

  2. 自己使用代碼製作。

用下面的列子來介紹相關的標籤

    vector_drawable.xml
    
    <vector xmlns:android="http://schemas.android.com/apk/res/  android"
        android:width="200dp"
        android:height="200dp"
        android:viewportHeight="1000"
        android:viewportWidth="1000">
         <group
            android:name="rotation"
            android:pivotX="500.0"
            android:pivotY="500.0"
            android:rotation="0.0">
            <path
                android:name="vector"
                android:fillColor="#00ffff"
                android:pathData="M67,750 L500,0  500,0  933,750 67,750  M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148  M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853" />
        </group>
    </vector>

注意到和普通SVG圖內容不同地方在與viewBox那變成了 viewportWidth, viewportHeight .

viewportWidth , viewportHeight 就相當於畫這個SVG的畫布大小。

width和height是規定這個SVG圖像最終的顯示大小的,一般用dp表示。

第二個不同是有一個普通SVG裏的fill到android裏要變成fillColor,這裏就是SVG圖像填充的顏色。

第三點不同是,普通SVG的path的數據是d開頭的標籤,在android裏要寫成pathData。

綜上所述,只要把viewBox的大小改成viewport的大小,把填充顏色的fill改成fillColor,把Path中的d,改成pathData就行了。
android:name="rotation" 爲group 和 path 加上 name 屬性 是爲了後面能便於加上動畫。

android:pathData="M67,750 L500,0  500,0  933,750 67,750  M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148  M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853"

M = moveto 相當於 android Path 裏的moveTo(),用於移動起始點
L = lineto 相當於 android Path 裏的lineTo(),用於畫線
H = horizontal lineto 用於畫水平線
V = vertical lineto 用於畫豎直線
C = curveto 相當於cubicTo(),三次貝塞爾曲線
S = smooth curveto 同樣三次貝塞爾曲線,更平滑
Q = quadratic Belzier curve quadTo(),二次貝塞爾曲線
T = smooth quadratic Belzier curveto 同樣二次貝塞爾曲線,更平滑
A = elliptical Arc 相當於arcTo(),用於畫弧
Z = closepath 相當於closeTo(),關閉path

把製作好的SVG圖片放置在 drawable 目錄下就可以用了。

<ImageView
    android:layout_width="250dp"
    android:layout_height="300dp"
    android:src="@drawable/vector_drawable"
    android:id="@+id/iv_main"/>

animated-vector

animated-vector 可以去創建一個矢量資源的動畫。

同樣的,創建出來的 vector_animation.xml 放置在 drawable 下。

animated-vector.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
             android:drawable="@drawable/vector_drawable" >

<target
        android:name="vector"
        android:animation="@anim/vector_anim" />

<target
        android:name="rotation"
        android:animation="@anim/vector_rotation" />
</animated-vector>

android:drawable="@drawable/vector_drawable" 設置矢量資源文件。

target 設置動畫,第一個爲 @drawable/vector_drawable 下 name 爲 vector 設置 動畫。第二個 同理。

以下是動畫效果文件: (動畫文件放置在 anim 文件目錄下)

vector_anim.xml 這個是製作了一個變形動畫

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M67,750 L500,0 500,0 933,750 67,750        M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148  M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853"
        android:valueTo="M147,853 L147,147 853,147 853,853 147,853    M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148  M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853"
        android:valueType="pathType" />

<objectAnimator
        android:startOffset="3000"
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M147,853 L147,147 853,147 853,853 147,853    M147,853 A 0.1,500 0 0 1 147,147 M147,147 A 500,0.1 0 0 1 853,147  M853,147 A 0.1,500 0 0 1 853,853 M851,853 A 500,0.1 0 0 1 147,853"
        android:valueTo="M147,853 L147,147 853,147 853,853 147,853      M147,853 A 500,500 0 0 1 147,147 M147,147 A 500,500 0 0 1 853,147  M853,147 A 500,500 0 0 1 853,853 M853,853 A 500,500 0 0 1 147,853"
        android:valueType="pathType" />
</set>

vector_rotation.xml 這個是製作了一個旋轉動畫

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="1440" />
</set>

使用該動畫:

<ImageView
    android:layout_width="250dp"
    android:layout_height="300dp"
    android:src="@drawable/vector_animation"
    android:id="@+id/iv_main"/>

開啓動畫的代碼:

final ImageView iv = (ImageView) findViewById(R.id.iv_main);
    iv.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if(iv.getDrawable() instanceof Animatable){
                //開始動畫
                ((Animatable) iv.getDrawable()).start();
            }
        }
    }); 

效果如下:



二、Lottie庫播放動畫

Android 5.x 之後提供了對 SVG 的支持,通過 VectorDrawable、AnimatedVectorDrawable 的結合可以實現一些稍微複雜的動畫,但是兼容性是一個問題,不過整個實現流程非常麻煩,每次全新實現一個動畫都得重頭來過,最最關鍵的是,如果一個公司下的 App,iOS 也要實現一套一樣的動畫,資源的佔用就顯得過大了。

而 Airbnb 開源的這個項目完美的解決以上難題

假設我們要做一個引導頁面的歡迎動畫,這個一般設計師會用 Adobe 旗下的 After Effects (簡稱 AE)來做個動畫出來,設計師用 AE 做個動畫比工程師用代碼去實現一個動畫要快的多的多,調整起來也很方便,之後 AE 上有一款插件叫做 Bodymovin,這個插件也比較屌,可以直接根據 AE 上的動畫文件導出 json 文件,這個 json 文件描述了該動畫的一些關鍵點的座標以及運動軌跡,之後我們在項目中引用 Lottie 開源庫,在佈局文件中簡單的加上這麼一句就完美的實現了。

在項目的build.gradle文件中加入:

dependencies {  
  compile 'com.airbnb.android:lottie:1.0.1'
  ...
}

使用Lottie

Lottie 支持Jellybean (API 16)及以上的系統,使用這個Lottie應該把 xxxxx.json 文件放在 app/src/main/assets 目錄下。

以下例子中把O.json文件放在規定的目錄下。

最簡單的使用方式是直接在佈局文件中添加:

<com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:lottie_fileName="O.json"
        app:lottie_loop="true"
        app:lottie_autoPlay="true" />

或者

佈局文件中:
<com.airbnb.lottie.LottieAnimationView
        android:id="@+id/animation_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

-----------------------------------------------------
代碼中:
LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.animation_view);
animationView.setAnimation("O.json");
//設置是否循環播放
animationView.loop(true);
//播放動畫
animationView.playAnimation();

注意的是:這方法將在後臺線程異步加載數據文件,並在加載完成後開始渲染顯示動畫.

效果如圖:

可以通過API控制動畫,並且設置一些監聽

animationView.addAnimatorUpdateListener((animation) -> {
    // Do something.
});

也可以使用以下方法進行對動畫的設置:

btnStop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //animationView.isAnimating()動畫是否在播放
            if (animationView.isAnimating()) {
                //動畫停止
                animationView.cancelAnimation();
            }
        }
    });

在使用遮罩的情況下,LottieAnimationView 使用 LottieDrawable來渲染動畫.如果需要的話,你可以直接使用drawable形式:

final LottieDrawable drawable = new LottieDrawable();
    LottieComposition.fromAssetFileName(this, "O.json", new LottieComposition.OnCompositionLoadedListener() {
        @Override
        public void onCompositionLoaded(LottieComposition composition) {
            drawable.setComposition(composition);
            drawable.loop(true);
            drawable.playAnimation();
        }
    });

如果你需要頻發使用某一個動畫,可以使用LottieAnimationView內置的一個緩存策略:

animationView.setAnimation("O.json", LottieAnimationView.CacheStrategy.Strong);
public enum CacheStrategy {
    None,
    Weak,
    Strong
}

其中CacheStrategy的值可以是Strong,Weak或者None,它們用來決定LottieAnimationView對已經加載並轉換好的動畫持有怎樣形式的引用(強引用/弱引用).


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章