❶ 安卓開發中矢量圖的繪制及動畫
矢量圖也稱為面向對象的圖像或繪圖圖像,是根據幾何特性來繪制的圖形,在安卓開發中可以使用失量圖代替原來的圖片資源,矢量圖具有佔用空間小和可以隨意縮放但不失真的優勢,在我的多個項目中都有運用。
通過學習和實踐,我總結了一些與矢量圖相關的知識,方便今後更好的使用矢量圖,同時也可以供大家查閱參考。
繪制矢量圖之前需要先定義畫布的寬高,後續的繪制效果都展示在這個畫布上。在繪制過程中需要輸入的坐標就是這個畫布上的點。
安卓的矢量圖常見於 drawable 文件夾下,是一個xml文件,由 vector 標簽包裹,在 vector 標簽中可包含多個 path 標簽,依次疊加顯示。
在矢量圖中最重要的就是 path 屬性,圖像的樣式就是由 path 屬性中的數據繪制而成,這些數據由不同的命令組合而成,下面就介紹一些矢量圖的繪制命令。
將前面的命令示例連接起來就可以生成一個完整的圖像,它大概長這個樣子:
畫布的尺寸為500x500,圖上的頂點是200,10的位置,也是我們開始作圖的起點。通過這個圖片可以更好的理解每一個繪圖命令。
安卓中可以為矢量圖添加動畫效果,這樣用戶就可以看到一個動的圖片,可以一定程度的提高app的交互效果。矢量圖動畫是圖形內部的變化,可以做到View動畫無法實現的效果。
這種動畫針對的是矢量圖中 path 欄位的值,通過連續改變 path 欄位的值而達到產生動畫的效果。
註:pathData動畫所需的AnimatedVectorDrawable最低要求API等級為25
實現一個矢量圖動畫需要以下幾步:
1. 准備起始狀態和結束狀態的矢量圖兩張。
2. 創建動畫配置文件。
3. 創建動畫矢量圖文件。
4. 啟動動畫。
基於這種要求,我准備了兩個矢量圖:
控制動畫運行的是一個 objectAnimator ,此處把 objectAnimator 包裹在一個 set 中也是可以的,說白了就是執行這個動畫文件。
ration 用來指定動畫的持續時間。
propertyName 中的pathData指的就是矢量圖中的pathData。
valueFrom 和 valueTo 一個是起始路徑,一個是結束路徑,可以想到,這個動畫就是在持續修改pathData,從而達到展示動畫的效果。而 valueFrom 和 valueTo 的值是直接從先前准備的矢量圖中復制過來的,所以那個結束狀態的矢量圖中唯一有用的東西就是pathData屬性,沒有那個文件也無所謂。
valueType 這里必須填判型寫pathType,這是專門用來計算path的類型。
此時,文件的最外層由 animated-vector 包裹,同時需要添加一個 drawable 參數,這個 drawable 用於指定動畫應用於那個矢量圖上,我們是要從未啟用狀態變成啟用狀態,所以是在未啟用狀態開始執行動畫,在動畫未開始的時候展示的也是未啟用狀態。此處我們指定為 @drawable/icon_filter_off 。
內部有一個 target 標簽,這個標簽可以有多個,分別對應不同的動畫,但同一個 path 只能應用一個動畫。
name 用於指定要執行動畫的 path 。status正是我們為右下角小圖標path設置的名稱。
animation 用於指定需要執行的動畫。此處引用我們剛剛創建的猛沖山動畫資源 @animator/filter_turn_on 。
當我們創建枝中好動畫矢量圖之後,頁面中引用的資源就不再是之前的靜態矢量圖了,需要把 ImageView 的圖片替換成 @drawable/animated_filter_on
經過這么多的步驟,我們終於做出了一個矢量圖動畫,而且是一個。說實話,有點累,然而我這個狀態切換的動畫一套就要兩個,所以我又加了一個回來的動畫和對應的動畫矢量圖,一共六個文件,完成了篩選狀態的兩個切換動畫。這還是比較簡單的實現方式,對於兩種狀態切換的動畫,網上還有一種使用selector的方式,這種方式更麻煩,而且使用方法並沒有簡單一些,所以我的選擇是在需要切換狀態的時候更改 ImageView 的圖片資源,然後再執行動畫。
trimPath動畫相當於是改變了矢量圖繪制的位置,是從頭開始畫還是從80%的位置開始畫,然後再動態的修改這個百分比,從而達到動畫的效果。理解起來倒不是很難。
先放一個我使用trimPath動畫做的loading效果,這個動畫效果被我用在LoadingDialog中,在界面載入的時候會重復播放這個動畫。
android:name="load" 不用多說,這個是我們做動畫時路徑名稱。這里為了讓心電圖路徑更清晰,我設置了描邊寬度為20( android:strokeWidth="20" ),同時還要設置描邊的顏色才能展示出來。後面的 android:trimPathStart="0" 和 android:trimPathEnd="0" 是本次trimPath動畫的重點。
這兩個屬性都設置為0是因為動畫的起始幀都為0,然後通過 objectAnimator 慢慢把這兩個屬性變為1,這樣一個慢慢增長的動畫就形成了。
網路上一個橫線變成搜索按鈕的示例是將這兩個屬性分別應用到了兩個 path 上,而我是將兩個屬性同時應用到一個 path 上,原理都是一樣的。
在配置文件中,我將兩個動畫都設置為3秒且循環播放,起始點的動畫慢於終點的動畫1秒,達到只畫中間1秒間隔線段的效果。和路徑變形動畫的區別是 android:valueType="floatType" ,我們只需要計算從0到1的數字,然後應用到 trimPathStart 和 trimPathEnd 欄位上。至此,loading的動畫就配置完了。
這一步已經沒什麼可說的了,就是將指定的矢量圖中指定的路徑設置一個指定的動畫。
通過幾天的學習,已經大致掌握了矢量圖的展示及動畫的製作,但這一套流程下來成本比較高,是程序員方式的動畫製作流程。除了製作成本,創意成本也是相當高的,一個好的創意能極大的提升用戶體驗,而好多時候我們的創意能夠被實現也是很困難的。希望以後能實現一些更好的效果,讓用戶使用起來更舒服。
SVG—最簡單的SVG動畫
SVG路徑(path)中的圓弧(A)指令的語法說明及計算邏輯
Android中的矢量圖
Android高級動畫(2)
❷ 如何使用Android的VectorDrawable類繪制矢量圖
繪制矢量圖形非難事——如何使用Android的VectorDrawable類
內容概述
盡管Android系統並不能夠直接支持SVG(即可縮放矢量圖形),但Lollipop版本卻引入了一個名為VectorDrawable的新類,其允許設計人員及開發人員以純代碼方式生成類似的繪制效果。
在今天的文章中,我們將共同學習如何利用XML文件創建一個VectorDrawable,並將其以動畫方式顯示在自己的項目當中。這項功能只能在運行有Android 5.0或者更高版本的設備上實現,而且目前還不具備任何支持庫實現。本篇教程中的相關源文件可以通過GitHub網站獲取。
1. 創建Vector Drawable
從相似角度來看,VectorDrawable與標准SVG圖形都是利用path值繪制完成的。不過如何利用SVG path繪制圖形並不在本篇文章的探討范圍之內,大家可以點擊此處從W3C網站處獲取必要的說明資料。在本文當中,我們只需要了解到path標簽的作用是進行圖形繪制即可。讓我們首先從SVG文件入手,看看以下圖形是如何被繪制出來的:
這一圖形共由五個主要部分所組成:
一個圓角四邊形作為CPU主體,該四邊形由兩條拱狀弧線構成。
四組各自包含五根線條的圖形,用於充當CPU的外延線路。
以下代碼所示為如何以SVG方式繪制以上圖形:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"> <path id="cpu" d=" M341.087,157.478c7.417,0,13.435,6.018,13.435,13.435v170.174 c0,7.417-6.018,13.435-13.435,13.435H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913 c0-7.417,6.018-13.435,13.435-13.435H341.087z M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785 0,35.826-16.041,35.826-35.826V157.478z M193.304,408.261V462h-17.913 v-53.739H193.304z M264.957,408.261V462h-17.914v-53.739H264.957z M300.783,408.261V462h-17.914v-53.739H300.783z M229.13,408.261 V462h-17.913v-53.739H229.13z M336.609,408.261V462h-17.914v-53.739H336.609z M193.304,50v53.739h-17.913V50H193.304z M264.957,50 v53.739h-17.914V50H264.957z M300.783,50v53.739h-17.914V50H300.783z M229.13,50v53.739h-17.913V50H229.13z M336.609,50v53.739 h-17.914V50H336.609z M408.261,318.695H462v17.914h-53.739V318.695z M408.261,247.043H462v17.914h-53.739V247.043z M408.261,211.217 H462v17.913h-53.739V211.217z M408.261,282.869H462v17.914h-53.739V282.869z M408.261,175.391H462v17.913h-53.739V175.391z M50,318.695h53.739v17.914H50V318.695z M50,247.043h53.739v17.914H50V247.043z M50,211.217h53.739v17.913H50V211.217z M50,282.869 h53.739v17.914H50V282.869z M50,175.391h53.739v17.913H50V175.391z" /> </svg>
雖然看起來有點繁雜,但大家其實用不著糾結於以上代碼的具體含義,而且這完全不會影響到我們接下來要進行的VectorDrawable繪制工作。不過需要強調的是,我將前面提到的五大圖形組成部分在代碼中作為獨立的區塊來處理,這是為了增強代碼內容的可讀性。
首先,我們需要利用兩條拱形弧線來繪制出圓角四邊形,而在接下來的內容中我們會探討如何分別表現出上、下、左、右四個方位的外延線條。為了將上述SVG代碼轉化為VectorDrawable,大家首先需要在XML當中定義vector對象。以下代碼提取自本篇文章示例代碼當中的vector_drawable_cpu.xml文件。
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600" > </vector>
在此之後,大家可以向其中添加path數據。下列代碼同樣被拆分成了五個不同的path標簽而非將其作為整體處理,這當然也是為了保證內容的可讀性。
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600" > <path android:name="cpu" android:fillColor="#000000" android:pathData=" M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z" /> <path android:name="wires_bottom" android:fillColor="#000000" android:pathData=" M193.304,408.261V462h-17.913 v-53.739H193.304z M264.957,408.261V462h-17.914v-53.739H264.957z M300.783,408.261V462h-17.914v-53.739H300.783z M229.13,408.261 V462h-17.913v-53.739H229.13z M336.609,408.261V462h-17.914v-53.739H336.609z" /> <path android:name="wires_top" android:fillColor="#000000" android:pathData=" M193.304,50v53.739h-17.913V50H193.304z M264.957,50 v53.739h-17.914V50H264.957z M300.783,50v53.739h-17.914V50H300.783z M229.13,50v53.739h-17.913V50H229.13z M336.609,50v53.739 h-17.914V50H336.609z" /> <path android:name="wires_right" android:fillColor="#000000" android:pathData=" M408.261,318.695H462v17.914h-53.739V318.695z M408.261,247.043H462v17.914h-53.739V247.043z M408.261,211.217 H462v17.913h-53.739V211.217z M408.261,282.869H462v17.914h-53.739V282.869z M408.261,175.391H462v17.913h-53.739V175.391z" /> <path android:name="wires_left" android:fillColor="#000000" android:pathData=" M50,318.695h53.739v17.914H50V318.695z M50,247.043h53.739v17.914H50V247.043z M50,211.217h53.739v17.913H50V211.217z M50,282.869 h53.739v17.914H50V282.869z M50,175.391h53.739v17.913H50V175.391z" /> </vector>
正如大家所見,每個path片段都只需要利用pathData屬性進行繪制。現在我們可以將VectorDrawable XML文件作為一個可繪制對象納入到標准ImageView當中,而且其能夠根據應用程序的實際需要任意進行尺寸縮放——完全不需要再修改任何Java代碼。
2. 為Vector Drawables添加動畫效果
現在我們已經了解了如何以純代碼方式創建圖形,接下來要做的是找點樂子——為其添加動畫效果。在以下動畫中,大家會發現作為延伸線路的各組線條會不斷指向並遠離CPU本體進行移動。
為了達到這一目標,大家需要將包含動畫效果的每個片段包含在一個<group>標簽當中。經過修改的vector_drawable_cpu.xml版本將如下所示:
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="64dp" android:width="64dp" android:viewportHeight="600" android:viewportWidth="600" > <group android:name="cpu_box"> <path android:name="cpu" android:fillColor="#000000" android:pathData=" M341.087,157.478 c7.417,0,13.435,6.018,13.435,13.435 v170.174c0,7.417-6.018,13.435-13.435,13.435 H170.913 c-7.417,0-13.435-6.018-13.435-13.435V170.913c0-7.417,6.018-13.435,13.435-13.435H341.087z M390.348,157.478 c0-19.785-16.041-35.826-35.826-35.826H157.479c-19.785,0-35.826,16.041-35.826,35.826v197.043 c0,19.785,16.041,35.826,35.826,35.826h197.043c19.785,0,35.826-16.041,35.826-35.826V157.478z "/> </group> <group android:name="bottom"> <path android:name="wires_bottom" android:fillColor="#000000" android:pathData=" M193.304,408.261V462h-17.913 v-53.739H193.304z M264.957,408.261V462h-17.914v-53.739H264.957z M300.783,408.261V462h-17.914v-53.739H300.783z M229.13,408.261 V462h-17.913v-53.739H229.13z M336.609,408.261V462h-17.914v-53.739H336.609z" /> </group> <group android:name="top"> <path android:name="wires_top" android:fillColor="#000000" android:pathData=" M193.304,50v53.739h-17.913V50H193.304z M264.957,50 v53.739h-17.914V50H264.957z M300.783,50v53.739h-17.914V50H300.783z M229.13,50v53.739h-17.913V50H229.13z M336.609,50v53.739 h-17.914V50H336.609z " /> </group> <group android:name="right"> <path android:name="wires_right" android:fillColor="#000000" android:pathData=" M408.261,318.695H462v17.914h-53.739V318.695z M408.261,247.043H462v17.914h-53.739V247.043z M408.261,211.217 H462v17.913h-53.739V211.217z M408.261,282.869H462v17.914h-53.739V282.869z M408.261,175.391H462v17.913h-53.739V175.391z" /> </group> <group android:name="left"> <path android:name="wires_left" android:fillColor="#000000" android:pathData=" M50,318.695h53.739v17.914H50V318.695z M50,247.043h53.739v17.914H50V247.043z M50,211.217h53.739v17.913H50V211.217z M50,282.869 h53.739v17.914H50V282.869z M50,175.391h53.739v17.913H50V175.391z" /> </group> </vector>
接下來,我們需要為每個動畫類型創建animator文件。在本次示例中,每組線路各使用一個animator,這就意味著共需要四個animator。以下代碼所示為上方線路的動畫效果,大家還需要為下、左、右線路設定類似的效果。每個animator XML文件都被包含在了本項目的示例代碼當中。
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <objectAnimator android:propertyName="translateY" android:valueType="floatType" android:valueFrom="0" android:valueTo="-10" android:repeatMode="reverse" android:repeatCount="infinite" android:ration="250" /> </set>
如大家所見,propertyName被設定為translateY,這意味著該動畫將沿Y軸方向移動。而valueFrom與valueTo則控制著位移的起點與終點。通過將repeatMode設置為reverse而repeatCount設置為infinite,整個動畫會一直循環下去,其效果則在VectorDrawable處體現出來。該動畫的ration被設定為250,其時長單位為毫秒。
為了將該動畫應用到自己的可繪制文件當中,大家需要創建一個新的animated-vector XML文件,從而將這些animator分配給各VectorDrawable組。以下代碼的作用是創建該animated_cpu.xml文件。
<?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/vector_drawable_cpu"> <target
http://mobile.51cto.com/news-478709.htm