Android 開發 VectorDrawable 矢量圖 (三)矢量圖動畫


簡介——矢量動畫2種方式與流程

矢量動畫有一些不一樣的細節這里需要提前了解,否則容易在后續使用的時候困惑。

group動畫

使用group包裹后的動畫,為什么要使用它來包裹path?因為屬性動畫要改變繪制的圖片屬性來實現動畫,可是path標簽中並沒有translateX和translateY屬性,因此,VectorDrawable要想使用屬性,就需要用group標簽來封裝path標簽,將屬性動畫作用在group標簽中,這里使用group標簽將vector圖片分成了兩組,如果圖片比較復雜,會將其分成多組。但是group不支持直接操作path的屬性。所以這種動畫形式是直接移動整個path或者矢量圖,它不能根據矢量圖參數來變化動畫。另外它的添加和啟動動畫方式與path的name的動畫不同。

path動畫

直接使用path的name的動畫,這個動畫支持trimPathStart、trimPathEnd、pathData,fillColorfillAlpha這幾種與path有關的屬性,這種動畫形式可以直接看懂,trimPathStart與trimPathEnd是繪制步驟動畫、pathData是改變參數動畫(變形動畫)。另外它的添加和啟動動畫方式與group包裹后的動畫不同。

基本流程:

  1. 創建矢量圖
  2. 創建animator目錄(注意!是animator目錄。不是anim目錄。)
  3. 在animator里添加動畫xml
  4. 在drawable目錄里創建 animated-vector 組合器文件,組合動畫xml與矢量圖xml
  5. 在View 添加這個組合器

屬性說明

set

一個set中可以有多個objectAnimator,通過ordering屬性控制執行順序。ordering:取值["sequentially"|"together"],  sequentially(默認)。

  • <set android:ordering="sequentially"> 順序執行objectAnimator
  • <set android:ordering="together"> 同時執行objectAnimator

objectAnimator

objectAnimator中一下這些屬性

  • propertyName 動畫屬性名稱
  • valueType 值的類型
  • valueFrom 動畫的起始值
  • valueTo 動畫的結束值
  • repeatCount 重復次數
  • repeatMode 重復模式
  • duration 動畫時長
  • interpolator 動畫插值
  • startOffset 動畫延遲開始時間

propertyName屬性(屬性名)

propertyName:指定動作屬性如下:

  • translateX  X軸移動
  • translateY  Y軸移動
  • trimPathStart  路徑開始
  • trimPathEnd   路徑結束
  • scaleX   X軸放大或者縮小比例
  • scaleY   Y軸放大或者縮小比例
  • rotation  旋轉
  • fillAlpha  透明度
  • fillColor  顏色

Vector里面的屬性基本上都可以(需要注意target里面綁定的是group就只能使用當前group的屬性,下級group或path等不能使用,綁定的path就只能使用當前path的屬性,clip-path一樣)。

valueType屬性(屬性值類型)

valueType:PropertyName指定屬性值的類型,共有四種類型,分別是:["intType"|"floatType"|"colorType"|pathType]。

valueFrom、valueTo屬性(動畫初始和結束值)

valueFrom:PropertyName指定屬性的初始值,值的類型為ValueType(如位置、顏色、透明、PathData等)。

valueTo:PropertyName指定屬性的結束值,值的類型為ValueType。

repeatCount、repeatMode屬性(動畫重復次數和樣式)

repeatCount:定義動畫重復次數,["infinite"]為無限次。

repeatMode:定義重復的行為 ["restart"|"reverse"], restart:直接跳到起始位置重新開始;reverse:倒退到起始位置重新開始。

duration屬性(動畫時間)

duration:動畫執行一次的時間,單位ms。

interpolator屬性(動畫過程控制)

interpolator:控制動畫的運行過程。Interpolator 定義了動畫的變化速度,可以實現勻速、正加速、負加速、無規則變加速等。可以自己定義,也可以使用默認的,列如:


Accelerate:加速,共有下面四種模式
["@android:interpolator/accelerate_decelerate"|"@android:interpolator/accelerate_cubic"|
"@android:interpolator/accelerate_quad"|"@android:interpolator/accelerate_ quint "]
accelerate_decelerate:在動畫開始與結束的地方速率改變比較慢,在中間的時候加速;
accelerate_cubic:擬合立方緩和函數的曲線加速。
accelerate_quad:曲線匹配的quadtratic緩解功能加速。
accelerate_ quint:曲線匹配功能昆特緩解加速。


Decelerate:減速,共有四種模式,同Accelerate。
["@android:interpolator/accelerate_decelerate"|"@android:interpolator/decelerate_cubic"|
"@android:interpolator/decelerate_quad"|"@android:interpolator/decelerate_ quint "]。


Anticipate:開始的時候向后然后向前甩["@android:interpolator/accelerate_decelerate"] 。        

     
AnticipateOvershoot:開始的時候向后然后向前甩一定值后返回最后的值["@android:interpolator/anticipate_overshoot"] 。
Bounce:動畫結束的時候彈起["@android:interpolator/bounce"] 。        
Cycle:動畫循環播放特定的次數,速率改變沿着正弦曲線["@android:interpolator/cycle"] 。
Linear:以常量速率改變["@android:interpolator/linear"] 。             
Overshoot:向前甩一定值后再回到原來位置["@android:interpolator/overshoot"]。

startOffset屬性(延時)

延遲播放的時間,單位ms,只延時第一次播放,重復播放時不延時。

 

實現動畫

group 包裹動畫:

例子1

效果圖:

步驟一  創建矢量圖

在drawable目錄

my_svg.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="50dp"
    android:height="50dp"
    android:viewportWidth="50.0"
    android:viewportHeight="50.0">

    <group
        android:name="ic_right_path">

    <path
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="5"
        android:pathData="M20,10 L35,27 M20,40 L35,24"/>

    </group>

</vector>

步驟二  創建動畫xml

 在animator目錄

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/decelerate_cubic"
    android:duration="3000"
    android:repeatMode="reverse"
    android:repeatCount="infinite"
    android:propertyName="translateX"
    android:valueFrom="0"
    android:valueTo="10"
    android:valueType="floatType">

</objectAnimator>

雖然上面已經說明過屬性了,但是我還是在啰嗦解釋一下:

動畫插補器:android:interpolator="@android:interpolator/decelerate_cubic"   這里使用的是快到最后動畫減速的屬性
動畫持續時間:android:duration="3000"  這里設置的是3秒
動畫重復模式:android:repeatMode="reverse" 這里設置的是倒退到起始位置重新開始動畫
動畫屬性:android:propertyName="translateX" 這里設置的是X軸移動
動畫開始值:   android:valueFrom="0"
動畫完成值:android:valueTo="10"
參數屬性:android:valueType="floatType"  這里設置的是浮點值

步驟三  創建組合器

在drawable目錄

arrow_anim.xml

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

    <target
        android:animation="@animator/ic_right_path_animator"
        android:name="ic_right_path"/>

</animated-vector>

步驟四  在布局xml上的ImageView里添加組合器 arrow_anim.xml

 <ImageView
        android:id="@+id/ic_anim"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:src="@drawable/arrow_anim"
        android:layout_centerInParent="true" />

步驟五  啟動動畫

mIcAnim = (ImageView)findViewById(R.id.ic_anim);
        mBtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Drawable drawable = mIcAnim.getDrawable();
                if (drawable instanceof Animatable) {
                    ((Animatable) drawable).start();

                }
            }
        });

直接使用path name的動畫:

trimPathStart屬性

例子1:

效果圖

步驟一 創建矢量圖

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="50dp"
    android:height="50dp"
    android:viewportWidth="50.0"
    android:viewportHeight="50.0">
    
    <path
        android:name="ic_right_path"
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="5"
        android:pathData="M20,10 L35,27 L20,40"/>
    
</vector>

步驟二  創建動畫xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/decelerate_cubic"
    android:duration="3000"
    android:repeatMode="reverse"
    android:repeatCount="infinite"
    android:propertyName="trimPathStart"
    android:valueFrom="0"
    android:valueTo="1"
    android:valueType="floatType">

</objectAnimator>

 

步驟三  創建組合器

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

    <target
        android:animation="@animator/ic_right_path_animator"
        android:name="ic_right_path"/>

</animated-vector>

 

步驟四  添加組合器和啟動動畫

這里可以使用2種形式,別問我為什么可以使用兩種。我也不知道為什么。。。

第一種就是上面使用group包裹的動畫的形式

第二種在代碼上添加,注意這里使用的是AnimatedVectorDrawable,這很重要。因為下面的pathData屬性必須使用它

mIcAnim = (ImageView)findViewById(R.id.ic_anim);
        mBtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AnimatedVectorDrawable drawable = (AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim);
                mIcAnim.setImageDrawable(drawable);
                if (drawable != null){
                    drawable.start();
                }
            }
        });

 

pathData屬性

例子1:

效果圖:

步驟一   創建矢量圖

在drawable目錄

my_svg.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="50dp"
    android:height="50dp"
    android:viewportWidth="50.0"
    android:viewportHeight="50.0">

    <path
        android:name="ic_right_path"
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="5"
        android:pathData="M20,10 L35,27 M0,25 L34,25 M20,40 L35,24"/>

</vector>

 步驟二 在animator目錄創建動畫xml 

ic_right_path_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/decelerate_cubic"
    android:duration="3000"
    android:repeatMode="reverse"
    android:repeatCount="infinite"
    android:propertyName="pathData"
    android:valueFrom="M20,10 L35,27 M0,25 L34,25 M20,40 L35,24"
    android:valueTo="M0,15 L40,15 M0,25 L40,25 M0,35 L40,35"
    android:valueType="pathType">

</objectAnimator>

 屬性已經在上面有說明了,請對着理解就行了,這里需要注意2點!注意2點!注意2點! 重要事情說三遍!

  • 第一點     android:valueType="pathType"  這里使用的參數格式是pathType
  • 第二點   矢量動畫要求初始幀的路徑命令序列(valueFrom)與結束幀的路徑命令序列(valueTo)內的命令必須一一對應,只有參數值可以不同,這樣才能插值,從而矢量動畫才能執行。否則編譯后運行時就崩潰了。

步驟三 創建組合器

arrow_anim.xml

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

    <target
        android:animation="@animator/ic_right_path_animator"
        android:name="ic_right_path"/>

</animated-vector>

添加動畫(這里的動畫輸入的時候沒有聯想輸入,屬於正常請手動敲完)與path名稱

 步驟四 給ImageView添加arrow_anim 在啟動動畫

        mIcAnim = (ImageView)findViewById(R.id.ic_anim);
        mBtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
           AnimatedVectorDrawable drawable =(AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim);
                mIcAnim.setImageDrawable(drawable);
                if (drawable != null){
                    drawable.start();
                }
            }
        });

注意!注意!注意!

1.請不要把arrow_anim組合器直接添加到View xml屬性里,必須在代碼上添加才可以,如果直接添加會報錯。

2.這里使用的是AnimatedVectorDrawable類型,添加到View和啟動動畫,請不要弄錯了。

例子2

 

 步驟一  創建矢量圖

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">

    <path
        android:fillColor="#FF000000"
        android:pathData="M15.5,9.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>

    <path
        android:fillColor="#FF000000"
        android:pathData="M8.5,9.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>

    <path
        android:fillColor="#FF000000"
        android:pathData="M11.99,2
        C6.47,2 2,6.48 2,12
        s4.47,10 9.99,10
        C17.52,22 22,17.52 22,12S17.52,2 11.99,2z
        M12,20
        c-4.42,0 -8,-3.58 -8,-8
        s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>

    <path
        android:name="expression"
        android:strokeColor="#FF000000"
        android:strokeWidth="1.5"
        android:pathData="M8,17 C 10,14 14,14 16,17"/>

</vector>

說明一下,這里我使用的笑臉是Android studio自帶的,一開始的想法是找一個哭臉和笑臉,然后直接找到嘴巴的屬性就行了。但是,坑大了,最后發現哭臉和笑臉的嘴巴屬性根本不一樣。沒有辦法最后我只能自己直接用三次貝賽曲線畫了一個嘴巴。使用各位大神如果想直接使用Android studio的矢量圖來做path值變化,請一定檢查清楚屬性是否一樣(只要有一個字母不同就不行!)

步驟二   創建動畫xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/decelerate_cubic"
    android:duration="3000"
    android:repeatMode="reverse"
    android:repeatCount="infinite"
    android:propertyName="pathData"
    android:valueFrom="M8,17 C 10,14 14,14 16,17"
    android:valueTo="M8,15 C 10,18 14,18 16,15"
    android:valueType="pathType">

</objectAnimator>

步驟三  創建組合器

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

    <target
        android:animation="@animator/expression"
        android:name="expression"/>

</animated-vector>

步驟四  向View添加組合器、啟動動畫

mIcAnim = (ImageView)findViewById(R.id.ic_anim);
        mBtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AnimatedVectorDrawable drawable = (AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim2);
                mIcAnim.setImageDrawable(drawable);
                if (drawable != null){
                    drawable.start();
                }
            }
        });

例子3

效果圖:

步驟一 創建矢量圖

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="100dp"
        android:height="100dp"
        android:viewportWidth="100.0"
        android:viewportHeight="100.0">
    <!---->
    <path
        android:fillColor="@color/colorPrimaryDark"
        android:pathData="M40,20 C 40,6.5 60,6.5 60,20
                          M40,20 C 40,33.5 60,33.5 60,20  "/>
    <!--軀干-->
    <path
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="16"
        android:pathData="M48.5,32 L45,60"/>
    <!--左手-->
    <path
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="10"
        android:pathData="M43,35 L25,45 25,55 "/>
    <!--右手-->
    <path
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="10"
        android:pathData="M50,36.3 L75,57"/>
    <!--左腿 M43,55 L30,70 L15,65-->
    <path
        android:name="left_leg"
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="10"
        android:pathData="M43,55 L30,70 L15,65"/>
    <!--右腿 -->
    <path
        android:name="right_leg"
        android:strokeColor="@color/colorPrimaryDark"
        android:strokeWidth="10"
        android:pathData="M47,55 L55,70 L60,90"/>

</vector>

預覽效果:

步驟 二 創建對應的動畫xml文件

創建左腿動畫 step_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set android:ordering="sequentially"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1500"
        android:propertyName="pathData"
        android:valueFrom="M43,55 L30,70 L15,65"
        android:valueTo="M43,55 L45,70 L35,85"
        android:valueType="pathType">

    </objectAnimator>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1500"
        android:propertyName="pathData"
        android:valueFrom="M43,55 L45,70 L35,85"
        android:valueTo="M47,55 L55 70 L60 90"
        android:valueType="pathType">

    </objectAnimator>
</set>

 注意!這里為了讓腿部動的不那么尷尬,所以我添加了一個中間值動畫。所以這里使用的是組合動畫,在set包裹下的objectAnimator 會使用 android:ordering="sequentially"屬性按順序運行動畫。注意,我取消了android:repeatMode="reverse"
    android:repeatCount="infinite"  這兩個屬性,並且使用默認的插補器,所以沒有配置插補器。

 

創建右腿動畫 step_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set android:ordering="sequentially"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1500"
        android:propertyName="pathData"
        android:valueFrom="M43,55 L30,70 L15,65"
        android:valueTo="M43,55 L45,70 L35,85"
        android:valueType="pathType">

    </objectAnimator>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1500"
        android:propertyName="pathData"
        android:valueFrom="M43,55 L45,70 L35,85"
        android:valueTo="M47,55 L55 70 L60 90"
        android:valueType="pathType">

    </objectAnimator>
</set>

步驟三 創建組合器

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

    <target
        android:animation="@animator/step_left"
        android:name="left_leg"/>

    <target
        android:animation="@animator/step_right"
        android:name="right_leg"/>

</animated-vector>

步驟四  啟動動畫

mIcAnim = (ImageView)findViewById(R.id.ic_anim);
        mBtnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                AnimatedVectorDrawable drawable = (AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim3);
                mIcAnim.setImageDrawable(drawable);
                if (drawable != null){
                    drawable.start();
                }
            }
        });
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM