安卓開(kāi)發(fā)中矢量圖的繪制及動(dòng)畫(huà)

前言

矢量圖也稱(chēng)為面向?qū)ο蟮膱D像或繪圖圖像槐壳,是根據(jù)幾何特性來(lái)繪制的圖形,在安卓開(kāi)發(fā)中可以使用失量圖代替原來(lái)的圖片資源,矢量圖具有占用空間小和可以隨意縮放但不失真的優(yōu)勢(shì)吨拗,在我的多個(gè)項(xiàng)目中都有運(yùn)用。

通過(guò)學(xué)習(xí)和實(shí)踐跟伏,我總結(jié)了一些與矢量圖相關(guān)的知識(shí)丢胚,方便今后更好的使用矢量圖,同時(shí)也可以供大家查閱參考受扳。

矢量圖的繪制

繪制矢量圖之前需要先定義畫(huà)布的寬高携龟,后續(xù)的繪制效果都展示在這個(gè)畫(huà)布上。在繪制過(guò)程中需要輸入的坐標(biāo)就是這個(gè)畫(huà)布上的點(diǎn)勘高。

安卓的矢量圖常見(jiàn)于drawable文件夾下峡蟋,是一個(gè)xml文件坟桅,由vector標(biāo)簽包裹,在vector標(biāo)簽中可包含多個(gè)path標(biāo)簽蕊蝗,依次疊加顯示仅乓。

vector標(biāo)簽的常用屬性:
android:width="200dp" - 預(yù)覽寬度
android:height="200dp" - 預(yù)覽高度
android:viewportWidth="1024" - 畫(huà)布寬度(下面path路徑中的點(diǎn)位位于畫(huà)布中)
android:viewportHeight="1024" - 畫(huà)布高度
android:tint="#FFFFFF" - 矢量圖著色(會(huì)對(duì)矢量圖的全部?jī)?nèi)容進(jìn)行統(tǒng)一著色,覆蓋原有顏色)

path標(biāo)簽的常用屬性
android:fillColor="#FFFFFF" - 填充顏色
android:pathData="M82,500H942V524H82V500" - 矢量圖路徑
android:strokeColor="#FFFFFF" - 邊框顏色蓬戚,默認(rèn)的邊框是透明的
android:strokeWidth="20" - 邊框的寬度

在矢量圖中最重要的就是path屬性夸楣,圖像的樣式就是由path屬性中的數(shù)據(jù)繪制而成,這些數(shù)據(jù)由不同的命令組合而成子漩,下面就介紹一些矢量圖的繪制命令豫喧。

  • M 設(shè)置畫(huà)筆的位置,語(yǔ)法:M坐標(biāo)
    M200,10 - 將畫(huà)筆移動(dòng)到200,10的位置幢泼。
  • L 從當(dāng)前位置連接一條直線(xiàn)至指定位置紧显,語(yǔ)法:L坐標(biāo)
    L300,100 - 從當(dāng)前位置連接一條直線(xiàn)到300,100位置。
  • H 保持縱坐標(biāo)不變缕棵,畫(huà)一條橫線(xiàn)至目標(biāo)橫坐標(biāo)位置孵班,語(yǔ)法:H橫坐標(biāo)
    H200 - 畫(huà)一條橫線(xiàn)至橫坐標(biāo)為200的點(diǎn)上。
  • V 保持橫坐標(biāo)不變招驴,畫(huà)一條豎線(xiàn)至目標(biāo)縱坐標(biāo)位置篙程,語(yǔ)法:V縱坐標(biāo)
    V200 - 畫(huà)一條豎線(xiàn)至縱坐標(biāo)為200的點(diǎn)上。
  • Q 連接目標(biāo)點(diǎn)位并對(duì)連線(xiàn)做二次貝塞爾曲線(xiàn)處理忽匈,語(yǔ)法:Q貝塞爾坐標(biāo)房午,目標(biāo)點(diǎn)坐標(biāo)
    Q300,100,400,200 - 連接當(dāng)前位置和400,200做一條直線(xiàn),在直線(xiàn)上做貝塞爾曲線(xiàn)變換丹允,變換的錨點(diǎn)為300,100郭厌。
  • C 連接目標(biāo)點(diǎn)位并對(duì)連線(xiàn)做三次貝塞爾曲線(xiàn)處理,語(yǔ)法:C貝塞爾坐標(biāo)1雕蔽,貝塞爾坐標(biāo)2折柠,目標(biāo)點(diǎn)坐標(biāo)
    C300,250,500,350,400,400 - 連接當(dāng)前位置和400,400做一條直線(xiàn),先用貝塞爾坐標(biāo)1對(duì)直線(xiàn)做一次變換批狐,再用貝塞爾坐標(biāo)2對(duì)之前的結(jié)果做一次變換扇售,最終會(huì)得到一個(gè)S型的線(xiàn)段。
  • A 連接起始點(diǎn)與目標(biāo)點(diǎn)嚣艇,再根據(jù)指定的半徑和角度繪制一個(gè)圓承冰,使線(xiàn)段的兩個(gè)端點(diǎn)都在圓的邊上,然后根據(jù)圓弧參數(shù)和繪制方向參數(shù)畫(huà)出所需的圓弧食零,語(yǔ)法:A橫向半徑困乒,縱向半徑,旋轉(zhuǎn)角度贰谣,圓弧大小娜搂,繪制方向迁霎,目標(biāo)坐標(biāo)
    A500,300,0,0,1,0,400 - 繪制圓弧的過(guò)程比較復(fù)雜,下面分步模擬一下百宇。
    1. 根據(jù)所指定的橫向半徑和縱向半徑先繪制一個(gè)橢圓考廉,如果兩個(gè)半徑一致就是一個(gè)正圓。
    2. 根據(jù)指定的旋轉(zhuǎn)角度對(duì)剛剛繪制的橢圓進(jìn)行旋轉(zhuǎn)携御,所傳入的角度與0-360度一一對(duì)應(yīng)昌粤,0=沒(méi)有旋轉(zhuǎn),90=把橢圓豎過(guò)來(lái)因痛,360=轉(zhuǎn)了一整圈婚苹,720=轉(zhuǎn)了兩圈岸更。
    3. 此時(shí)一個(gè)目標(biāo)橢圓已經(jīng)形成鸵膏,然后需要用起點(diǎn)和終點(diǎn)連成線(xiàn)段去切割這個(gè)橢圓,使起點(diǎn)和終點(diǎn)恰好都在橢圓的邊上怎炊,如果橢圓很小谭企,會(huì)將橢圓等比放大至兩點(diǎn)位置。
    4. 在上一步中有兩種情況评肆,一個(gè)是橢圓比較小债查,放大后兩點(diǎn)連線(xiàn)為橢圓的直徑,這時(shí)圓弧大小的參數(shù)就沒(méi)用了瓜挽,寫(xiě)1或0都行盹廷。如果橢圓比較大,那么符合兩點(diǎn)都在橢圓邊上情況的位置就有兩個(gè)久橙,此時(shí)如果從起點(diǎn)到終點(diǎn)順時(shí)針去畫(huà)圓弧就會(huì)有一個(gè)大圓弧一個(gè)小圓弧俄占,如果我們需要大圓弧的情況就把圓弧大小的參數(shù)設(shè)置為1,反之則設(shè)置為0淆衷。
    5. 接下來(lái)的一個(gè)參數(shù)是繪制順序缸榄,繪制順序?yàn)?的時(shí)候是順時(shí)針繪制,繪制順序?yàn)?的時(shí)候是逆時(shí)針繪制祝拯,一般我們都會(huì)先根據(jù)圖像的需求指定繪制順序甚带,再根據(jù)繪制順序指定圓弧大小參數(shù)。
    6. 最后的一個(gè)參數(shù)是目標(biāo)坐標(biāo)佳头,這個(gè)坐標(biāo)在第三步的時(shí)候已經(jīng)使用了鹰贵,此時(shí)我們需要的圓弧就已經(jīng)畫(huà)完了。
  • Z 閉合圖形康嘉,將當(dāng)前位置與路徑起始點(diǎn)連接起來(lái)

將前面的命令示例連接起來(lái)就可以生成一個(gè)完整的圖像碉输,它大概長(zhǎng)這個(gè)樣子:


矢量圖繪制命令示例

畫(huà)布的尺寸為500x500,圖上的頂點(diǎn)是200,10的位置凄鼻,也是我們開(kāi)始作圖的起點(diǎn)腊瑟。通過(guò)這個(gè)圖片可以更好的理解每一個(gè)繪圖命令聚假。

  • 以上的繪制命令均有其對(duì)應(yīng)的小寫(xiě)版本,M-m L-l H-h V-v Q-q C-c A-a闰非,小寫(xiě)版本的功能與大寫(xiě)版本一致膘格,但其中的坐標(biāo)都替換成了相對(duì)位置,使用相對(duì)位置的好處是起點(diǎn)發(fā)生變化后财松,后面的路徑自動(dòng)跟隨起點(diǎn)移動(dòng)瘪贱,不需要所有的路徑都調(diào)整參數(shù)。

  • 安卓矢量圖的路徑會(huì)自動(dòng)閉合辆毡,結(jié)尾沒(méi)有加Z命令也和添加了Z命令的效果一致菜秦。

矢量圖動(dòng)畫(huà)

安卓中可以為矢量圖添加動(dòng)畫(huà)效果,這樣用戶(hù)就可以看到一個(gè)動(dòng)的圖片舶掖,可以一定程度的提高app的交互效果球昨。矢量圖動(dòng)畫(huà)是圖形內(nèi)部的變化,可以做到View動(dòng)畫(huà)無(wú)法實(shí)現(xiàn)的效果眨攘。

pathData動(dòng)畫(huà)

這種動(dòng)畫(huà)針對(duì)的是矢量圖中path字段的值主慰,通過(guò)連續(xù)改變path字段的值而達(dá)到產(chǎn)生動(dòng)畫(huà)的效果。

注:pathData動(dòng)畫(huà)所需的AnimatedVectorDrawable最低要求API等級(jí)為25

實(shí)現(xiàn)一個(gè)矢量圖動(dòng)畫(huà)需要以下幾步:
1. 準(zhǔn)備起始狀態(tài)和結(jié)束狀態(tài)的矢量圖兩張鲫售。
2. 創(chuàng)建動(dòng)畫(huà)配置文件共螺。
3. 創(chuàng)建動(dòng)畫(huà)矢量圖文件。
4. 啟動(dòng)動(dòng)畫(huà)情竹。

  • 首先藐不,我們準(zhǔn)備用于動(dòng)畫(huà)的兩張矢量圖,分別代表動(dòng)畫(huà)的起始樣式和結(jié)束樣式秦效,而且這兩張圖執(zhí)行動(dòng)畫(huà)的path必須是同形path雏蛮。

通過(guò)對(duì)矢量圖繪制的了解,我們知道矢量圖就是一個(gè)一個(gè)的點(diǎn)位進(jìn)行直線(xiàn)或曲線(xiàn)連接形成的一個(gè)圖形棉安,所以在做矢量圖變化的時(shí)候底扳,系統(tǒng)是把我們初始各個(gè)點(diǎn)位的坐標(biāo)通過(guò)系統(tǒng)計(jì)算后逐漸的改變成了結(jié)束時(shí)的坐標(biāo),這就要求我們做動(dòng)畫(huà)的兩個(gè)矢量圖點(diǎn)位的個(gè)數(shù)是一致的贡耽,同時(shí)由于系統(tǒng)比較傻衷模,只能是直線(xiàn)轉(zhuǎn)直線(xiàn),曲線(xiàn)轉(zhuǎn)曲線(xiàn)蒲赂,所以這兩張圖的路徑命令及順序也要一致阱冶。這就是傳說(shuō)中的同形path

基于這種要求滥嘴,我準(zhǔn)備了兩個(gè)矢量圖:

// icon_filter_off.xml 未啟用篩選功能時(shí)的樣式
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="200dp"
    android:tint="#000000"
    android:viewportWidth="1024"
    android:viewportHeight="1024">

    <path
        android:fillColor="#000000"
        android:pathData="M102,112L282,382V912Q282,942,322,912L482,792V382L812,100Q832,82,812,82H122Q82,82,102,112" />

    <path
        android:name="status"
        android:fillColor="#000000"
        android:pathData="M582,490L582,530L882,530L882,490ZM582,640L582,680L882,680L882,640ZM582,790L582,830L882,830L882,790Z" />
</vector>
icon_filter_off.xml 展示效果
// icon_filter_on.xml 啟用了篩選功能時(shí)的樣式
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="200dp"
    android:tint="#000000"
    android:viewportWidth="1024"
    android:viewportHeight="1024">

    <path
        android:fillColor="#000000"
        android:pathData="M102,112L282,382V912Q282,942,322,912L482,792V382L812,100Q832,82,812,82H122Q82,82,102,112" />

    <path
        android:name="status"
        android:fillColor="#000000"
        android:pathData="M592,670L562,700L662,800L692,770ZM662,800L692,830L792,730L762,700ZM762,700L792,730L892,630L862,600Z" />
</vector>

icon_filter_on.xml 展示效果

我的目標(biāo)是在狀態(tài)切換時(shí)把右下角的小圖標(biāo)做一個(gè)動(dòng)畫(huà)轉(zhuǎn)換木蹬,所以右下角的路徑是單獨(dú)寫(xiě)了一個(gè)path,同時(shí)把path命名為status若皱。
這兩個(gè)矢量圖是我通過(guò)代碼敲出來(lái)的镊叁,也滿(mǎn)足了同形path的要求尘颓,為了這兩個(gè)矢量圖,我把小學(xué)和初中的數(shù)學(xué)知識(shí)又都搬了出來(lái)晦譬,一通計(jì)算疤苹,才算出了這些坐標(biāo),可惜還是沒(méi)能達(dá)到我的心理預(yù)期敛腌,只能先湊合用卧土。

  • 接下來(lái)開(kāi)始創(chuàng)建動(dòng)畫(huà)配置。
    res\animator文件夾下創(chuàng)建filter_turn_on.xml文件像樊,代碼如下:
// filter_turn_on.xml 動(dòng)畫(huà)的配置文件
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:propertyName="pathData"
    android:valueFrom="M582,490L582,530L882,530L882,490ZM582,640L582,680L882,680L882,640ZM582,790L582,830L882,830L882,790Z"
    android:valueTo="M592,670L562,700L662,800L692,770ZM662,800L692,830L792,730L762,700ZM762,700L792,730L892,630L862,600Z"
    android:valueType="pathType" />

控制動(dòng)畫(huà)運(yùn)行的是一個(gè)objectAnimator尤莺,此處把objectAnimator包裹在一個(gè)set中也是可以的,說(shuō)白了就是執(zhí)行這個(gè)動(dòng)畫(huà)文件生棍。
duration用來(lái)指定動(dòng)畫(huà)的持續(xù)時(shí)間颤霎。
propertyName中的pathData指的就是矢量圖中的pathData。
valueFromvalueTo一個(gè)是起始路徑足绅,一個(gè)是結(jié)束路徑捷绑,可以想到,這個(gè)動(dòng)畫(huà)就是在持續(xù)修改pathData氢妈,從而達(dá)到展示動(dòng)畫(huà)的效果。而valueFromvalueTo的值是直接從先前準(zhǔn)備的矢量圖中復(fù)制過(guò)來(lái)的段多,所以那個(gè)結(jié)束狀態(tài)的矢量圖中唯一有用的東西就是pathData屬性首量,沒(méi)有那個(gè)文件也無(wú)所謂。
valueType這里必須填寫(xiě)pathType进苍,這是專(zhuān)門(mén)用來(lái)計(jì)算path的類(lèi)型加缘。

  • 動(dòng)畫(huà)創(chuàng)建好了之后就開(kāi)始創(chuàng)建動(dòng)畫(huà)矢量圖文件。
    之前我們通過(guò)@drawable/icon_filter_off的方式就可以引用矢量圖觉啊,此時(shí)的矢量圖是靜態(tài)的拣宏,因?yàn)檫@個(gè)矢量圖最外層由vector包裹,現(xiàn)在需要一個(gè)動(dòng)態(tài)的矢量圖杠人,所以我們?cè)?code>res\drawable文件夾下創(chuàng)建animated_filter_on.xml勋乾,代碼如下:
// animated_filter_on.xml 動(dòng)畫(huà)矢量圖文件
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_filter_off">
    <target
        android:name="status"
        android:animation="@animator/filter_turn_on" />
</animated-vector>

此時(shí),文件的最外層由animated-vector包裹嗡善,同時(shí)需要添加一個(gè)drawable參數(shù)辑莫,這個(gè)drawable用于指定動(dòng)畫(huà)應(yīng)用于那個(gè)矢量圖上,我們是要從未啟用狀態(tài)變成啟用狀態(tài)罩引,所以是在未啟用狀態(tài)開(kāi)始執(zhí)行動(dòng)畫(huà)各吨,在動(dòng)畫(huà)未開(kāi)始的時(shí)候展示的也是未啟用狀態(tài)。此處我們指定為@drawable/icon_filter_off袁铐。
內(nèi)部有一個(gè)target標(biāo)簽揭蜒,這個(gè)標(biāo)簽可以有多個(gè)横浑,分別對(duì)應(yīng)不同的動(dòng)畫(huà),但同一個(gè)path只能應(yīng)用一個(gè)動(dòng)畫(huà)屉更。
name用于指定要執(zhí)行動(dòng)畫(huà)的path伪嫁。status正是我們?yōu)橛蚁陆切D標(biāo)path設(shè)置的名稱(chēng)。
animation用于指定需要執(zhí)行的動(dòng)畫(huà)偶垮。此處引用我們剛剛創(chuàng)建的動(dòng)畫(huà)資源@animator/filter_turn_on张咳。
當(dāng)我們創(chuàng)建好動(dòng)畫(huà)矢量圖之后,頁(yè)面中引用的資源就不再是之前的靜態(tài)矢量圖了似舵,需要把ImageView的圖片替換成@drawable/animated_filter_on

  • 準(zhǔn)備工作已經(jīng)就緒脚猾,接下來(lái)就讓我們的矢量圖動(dòng)起來(lái)。
    在點(diǎn)擊事件中將ImageViewdrawable提取出來(lái)砚哗,將其轉(zhuǎn)換成android.graphics.drawable.AnimatedVectorDrawable類(lèi)型龙助,然后調(diào)用start()方法即可。
// java
AnimatedVectorDrawable drawable= (AnimatedVectorDrawable) imageViewFilter.getDrawable();
drawable.start();

// kotlin
(imageViewFilter.drawable as AnimatedVectorDrawable).start()

經(jīng)過(guò)這么多的步驟蛛芥,我們終于做出了一個(gè)矢量圖動(dòng)畫(huà)提鸟,而且是一個(gè)。說(shuō)實(shí)話(huà)仅淑,有點(diǎn)累称勋,然而我這個(gè)狀態(tài)切換的動(dòng)畫(huà)一套就要兩個(gè),所以我又加了一個(gè)回來(lái)的動(dòng)畫(huà)和對(duì)應(yīng)的動(dòng)畫(huà)矢量圖涯竟,一共六個(gè)文件赡鲜,完成了篩選狀態(tài)的兩個(gè)切換動(dòng)畫(huà)。這還是比較簡(jiǎn)單的實(shí)現(xiàn)方式庐船,對(duì)于兩種狀態(tài)切換的動(dòng)畫(huà)银酬,網(wǎng)上還有一種使用selector的方式,這種方式更麻煩筐钟,而且使用方法并沒(méi)有簡(jiǎn)單一些揩瞪,所以我的選擇是在需要切換狀態(tài)的時(shí)候更改ImageView的圖片資源,然后再執(zhí)行動(dòng)畫(huà)篓冲。

// kotlin
// 這是點(diǎn)擊事件中切換狀態(tài)樣式的代碼李破,實(shí)際業(yè)務(wù)中可能會(huì)根據(jù)業(yè)務(wù)數(shù)據(jù)判斷是否需要切換。
imageViewFilter.run {
    if (isSelected) {
        setImageResource(R.drawable.animated_filter_off)
        (drawable as AnimatedVectorDrawable).start()
    }else{
        setImageResource(R.drawable.animated_filter_on)
        (drawable as AnimatedVectorDrawable).start()
    }
    isSelected = !isSelected
}

trimPath動(dòng)畫(huà)

trimPath動(dòng)畫(huà)相當(dāng)于是改變了矢量圖繪制的位置喷屋,是從頭開(kāi)始畫(huà)還是從80%的位置開(kāi)始畫(huà),然后再動(dòng)態(tài)的修改這個(gè)百分比密任,從而達(dá)到動(dòng)畫(huà)的效果涌萤。理解起來(lái)倒不是很難。

先放一個(gè)我使用trimPath動(dòng)畫(huà)做的loading效果,這個(gè)動(dòng)畫(huà)效果被我用在LoadingDialog中,在界面加載的時(shí)候會(huì)重復(fù)播放這個(gè)動(dòng)畫(huà)老玛。

loading

為了做到這種效果镜廉,我們一共需要以下幾個(gè)步驟:
1. 設(shè)計(jì)矢量圖塔插,并將其添加到安卓項(xiàng)目中。
2. 根據(jù)動(dòng)畫(huà)需求,添加動(dòng)畫(huà)配置文件茸炒。
3. 配置動(dòng)畫(huà)矢量圖文件壁公,在使用的地方進(jìn)行引用感论。
4. 開(kāi)始執(zhí)行動(dòng)畫(huà)。

  • 首先是設(shè)計(jì)一個(gè)自己的線(xiàn)狀動(dòng)畫(huà)贮尖,我的靈感來(lái)自于心電圖笛粘,一個(gè)人活著的話(huà)會(huì)有一個(gè)周期性的心電圖波動(dòng),而我用這個(gè)形狀來(lái)代表APP正在干活湿硝。在學(xué)習(xí)了矢量圖的繪制之后薪前,一個(gè)心電圖的形狀并不難,只是計(jì)算坐標(biāo)比較累关斜。
// icno_loading.xml loading的完全體樣式
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:width="200dp"
    android:height="200dp"
    android:tint="#000000"
    android:viewportWidth="1024"
    android:viewportHeight="1024">

    <path
        android:name="load"
        android:pathData="M82,512h280l60,-172l60,430l80,-602l70,430l30,-86h280"
        android:strokeWidth="20"
        android:strokeColor="#000000"
        android:trimPathStart="0"
        android:trimPathEnd="0"
        tools:trimPathEnd="1" />
</vector>

android:name="load"不用多說(shuō)示括,這個(gè)是我們做動(dòng)畫(huà)時(shí)路徑名稱(chēng)。這里為了讓心電圖路徑更清晰痢畜,我設(shè)置了描邊寬度為20(android:strokeWidth="20")垛膝,同時(shí)還要設(shè)置描邊的顏色才能展示出來(lái)。后面的android:trimPathStart="0"android:trimPathEnd="0"是本次trimPath動(dòng)畫(huà)的重點(diǎn)丁稀。

android:trimPathStart="0" - 路徑繪制的起始點(diǎn)吼拥,范圍[0,1]。
android:trimPathEnd="0" - 路徑繪制的終點(diǎn)线衫,范圍[0,1]凿可。

實(shí)際展示的效果就是從起點(diǎn)畫(huà)到終點(diǎn)的路徑。當(dāng)繪制范圍超過(guò)[0,1]時(shí)也可以畫(huà)出來(lái)授账,類(lèi)似于循環(huán)繪制枯跑。具體效果就自行體會(huì)吧。

這兩個(gè)屬性都設(shè)置為0是因?yàn)閯?dòng)畫(huà)的起始幀都為0白热,然后通過(guò)objectAnimator慢慢把這兩個(gè)屬性變?yōu)?敛助,這樣一個(gè)慢慢增長(zhǎng)的動(dòng)畫(huà)就形成了。
網(wǎng)絡(luò)上一個(gè)橫線(xiàn)變成搜索按鈕的示例是將這兩個(gè)屬性分別應(yīng)用到了兩個(gè)path上屋确,而我是將兩個(gè)屬性同時(shí)應(yīng)用到一個(gè)path上纳击,原理都是一樣的续扔。

  • 接下來(lái)為剛剛預(yù)留的屬性配置動(dòng)畫(huà)效果,要做到和心電圖差不多的掃描效果评疗,要同時(shí)修改路徑的起始點(diǎn)和終點(diǎn)测砂,這樣可以只展示整個(gè)路徑中的某一段。而且兩個(gè)動(dòng)畫(huà)要有一定間隔百匆,如果同步執(zhí)行砌些,起點(diǎn)和終點(diǎn)肯定是一致的,這樣什么都畫(huà)不出來(lái)加匈。
// loading.xml loading動(dòng)畫(huà)配置
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <objectAnimator
        android:duration="3000"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="trimPathStart"
        android:repeatCount="infinite"
        android:startOffset="1000"
        android:valueFrom="0"
        android:valueTo="1"
        android:valueType="floatType" />

    <objectAnimator
        android:duration="3000"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:propertyName="trimPathEnd"
        android:repeatCount="infinite"
        android:valueFrom="0"
        android:valueTo="1"
        android:valueType="floatType" />
</set>

在配置文件中存璃,我將兩個(gè)動(dòng)畫(huà)都設(shè)置為3秒且循環(huán)播放,起始點(diǎn)的動(dòng)畫(huà)慢于終點(diǎn)的動(dòng)畫(huà)1秒雕拼,達(dá)到只畫(huà)中間1秒間隔線(xiàn)段的效果纵东。和路徑變形動(dòng)畫(huà)的區(qū)別是android:valueType="floatType",我們只需要計(jì)算從0到1的數(shù)字啥寇,然后應(yīng)用到trimPathStarttrimPathEnd字段上偎球。至此,loading的動(dòng)畫(huà)就配置完了辑甜。

  • 所需的資源都準(zhǔn)備好了之后就創(chuàng)建一個(gè)動(dòng)畫(huà)矢量圖文件衰絮,在這個(gè)文件中將靜態(tài)的矢量圖和動(dòng)畫(huà)配置綁定到一起。
// animated_loading.xml 用于界面的動(dòng)畫(huà)矢量圖文件
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_loading">

    <target
        android:name="load"
        android:animation="@animator/loading" />
</animated-vector>

這一步已經(jīng)沒(méi)什么可說(shuō)的了磷醋,就是將指定的矢量圖中指定的路徑設(shè)置一個(gè)指定的動(dòng)畫(huà)猫牡。

  • 最后料滥,將animated_loading設(shè)置到目標(biāo)ImageView中性穿,在合適的時(shí)機(jī)開(kāi)始動(dòng)畫(huà)矾利。啟動(dòng)動(dòng)畫(huà)的方式和路徑變換一致靶衍,然后就可以欣賞自己制作的動(dòng)畫(huà)效果了。

結(jié)語(yǔ)

通過(guò)幾天的學(xué)習(xí)漩绵,已經(jīng)大致掌握了矢量圖的展示及動(dòng)畫(huà)的制作鼻由,但這一套流程下來(lái)成本比較高寇仓,是程序員方式的動(dòng)畫(huà)制作流程你雌。除了制作成本归薛,創(chuàng)意成本也是相當(dāng)高的,一個(gè)好的創(chuàng)意能極大的提升用戶(hù)體驗(yàn)匪蝙,而好多時(shí)候我們的創(chuàng)意能夠被實(shí)現(xiàn)也是很困難的。希望以后能實(shí)現(xiàn)一些更好的效果习贫,讓用戶(hù)使用起來(lái)更舒服逛球。

參考文章

SVG—最簡(jiǎn)單的SVG動(dòng)畫(huà)
SVG路徑(path)中的圓弧(A)指令的語(yǔ)法說(shuō)明及計(jì)算邏輯
Android中的矢量圖
Android高級(jí)動(dòng)畫(huà)(2)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市苫昌,隨后出現(xiàn)的幾起案子颤绕,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奥务,死亡現(xiàn)場(chǎng)離奇詭異物独,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)氯葬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)挡篓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人帚称,你說(shuō)我怎么就攤上這事官研。” “怎么了闯睹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵戏羽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我楼吃,道長(zhǎng)始花,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任孩锡,我火速辦了婚禮酷宵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘浮创。我一直安慰自己忧吟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布斩披。 她就那樣靜靜地躺著溜族,像睡著了一般。 火紅的嫁衣襯著肌膚如雪垦沉。 梳的紋絲不亂的頭發(fā)上煌抒,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音厕倍,去河邊找鬼寡壮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛讹弯,可吹牛的內(nèi)容都是我干的况既。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼组民,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼棒仍!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起臭胜,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤莫其,失蹤者是張志新(化名)和其女友劉穎癞尚,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乱陡,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浇揩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了憨颠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胳徽。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖烙心,靈堂內(nèi)的尸體忽然破棺而出膜廊,到底是詐尸還是另有隱情,我是刑警寧澤淫茵,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布爪瓜,位于F島的核電站,受9級(jí)特大地震影響匙瘪,放射性物質(zhì)發(fā)生泄漏铆铆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一丹喻、第九天 我趴在偏房一處隱蔽的房頂上張望薄货。 院中可真熱鬧,春花似錦碍论、人聲如沸谅猾。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)税娜。三九已至,卻和暖如春藏研,著一層夾襖步出監(jiān)牢的瞬間敬矩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工蠢挡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弧岳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓业踏,卻偏偏與公主長(zhǎng)得像禽炬,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子勤家,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容