Vector
優勢VectorDrawable
主要有兩個優勢:屏幕自適應和體積小。android
png
或者jpg
圖片,那麼爲了能讓圖片在不一樣分辨率的機型上可以很好地展示,一般會在各個drawable
文件夾下放置不一樣分辨率大小的圖片文件,而VectorDrawable
則不須要,僅僅只使用一套資源,就可以適應任何分辨率的手機。VectorDrawable
素材的大小要比png
和jpg
小不少。SVG
和Vector
的基本概念下面,咱們先介紹一下SVG
和VectorDrawable
的基本概念:緩存
SVG
:它並非Android
平臺特有的概念,它的全稱爲可縮放矢量圖形,簡單的來講,就是用於描述二維矢量圖形的圖形格式,更加詳細的解釋能夠參考:SVG - 百度百科。VectorDrawable
:它是Android
當中的SVG
實現,它並不支持SVG
的所有語法,只是支持部分有必要的部分。VectorDrawable
俗話說的好,巧婦難爲無米炊,這一節咱們就來介紹一下如何得到一個VectorDrawable
,通常獲取的方式有如下三種方式:bash
SVG
素材,再經過工具轉換成爲VectorDrawable
Android Studio
中的素材庫,直接獲取VectorDrawable
Vector
的語法,本身描述SVG
素材,再經過工具轉換成爲VectorDrawable
首先獲取SVG
素材,再將它轉換成爲VectorDrawable
是最經常使用的方式,而SVG
素材的獲取又有如下幾種途徑:app
SVG
圖像UI
設計師使用專業的工具導出png
和jpg
素材轉換爲SVG
圖像對於我的開發者而言,通常都會採用第一種方式,咱們這裏也只介紹第一種方式。不少文章都推薦過這個網站:iconFront - 阿里巴巴,它提供了SVG
和PNG
素材的直接下載: eclipse
Android Studio
的
New
選項中,選擇
Vector Asset
:
Local file
,並打開咱們下載後的圖像,再選擇
next
保存到指定的文件夾:
*.xml
文件,這個就是
VectorDrawable
:
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="1024.0"
android:viewportWidth="1024.0"
android:width="24dp">
<path android:fillColor="#FF000000"
android:pathData="M887.9,298.2c-12.9,-12.1 -33.2,-11.5 -45.2,1.4L415.9,754l-233.1,-229.7C170.2,511.9 150,512 137.5,524.6c-12.4,12.6 -12.3,32.9 0.4,45.2l256.5,252.7c0.1,0.1 0.2,0.1 0.3,0.2 0.1,0.1 0.1,0.2 0.2,0.3 2,1.9 4.4,3 6.8,4.3 1.2,0.7 2.1,1.7 3.4,2.1 3.8,1.5 7.8,2.2 11.7,2.2 4.2,0 8.4,-0.8 12.3,-2.5 1.3,-0.5 2.3,-1.7 3.6,-2.4 2.4,-1.4 4.9,-2.6 6.9,-4.7 0.1,-0.1 0.1,-0.3 0.2,-0.4 0.1,-0.1 0.2,-0.1 0.3,-0.2l449.2,-478.2C901.4,330.6 900.8,310.3 887.9,298.2z"/>
</vector>
複製代碼
Android Studio
中的素材庫,直接獲取VectorDrawable
仍是在上面的那個界面,咱們勾選另一個選項: ide
Material Design
提供的素材庫:
*.xml
的
VectorDrawable
:
<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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
複製代碼
Vector
的語法,本身描述在3.1
和3.2
當中,咱們能夠看到,最終VectorDrawable
都是用一個*.xml
來表示的,那麼,咱們固然能夠根據SVG
的語法,來編寫一個xml
文件,經過pathData
屬性進行描述,不過這種方式較爲繁瑣,通常不會採用。工具
Vector
語法雖說大多數狀況下,咱們不會徹底手動去編寫Vector
的xml
文件,可是,對於Vector
的基本語法仍是有必要了解一些的,由於在咱們後邊談到的動態Vector
中須要瞭解對於每一個標籤有哪些屬性能夠設置,Vector
包含下面三種標籤:佈局
<vector>
<group>
<path>
<path>
</group>
</vector>
複製代碼
<vector>
標籤name
:矢量圖的名字width, height
:矢量圖的固有寬高,一般使用dp
。viewportWidth, viewportHeight
:把矢量圖的寬高分紅多少個單元,這裏的每一個單元就對應pathData
中的一個點座標。<path>
標籤name
:路徑的名稱。fillColor
:圖形的填充顏色。pathData
:定義控制點的位置,相似與Canvas
當中的Path
類。<group>
標籤<group>
用來把多個<path>
組合在一塊兒,進行相同的處理。性能
更多的屬性能夠查閱下面這兩篇文章:gradle
VectorDrawable 詳解 Android 中的 SVG 圖像的各個屬性意義
Vector
的兼容性問題爲了讓VectorDrawable
可以在Android 5.0
如下版本的手機上使用,咱們須要引入support
包,並修改gradle
的配置。
support
包VectorDrawable
是在Android 5.0
以後提出來的,所以,若是咱們須要在低版本上使用,那麼就要引入com.android.support:appcompat-v7
包,要求版本號大於等於23.2.0
,這裏咱們選用的是:
compile 'com.android.support:appcompat-v7:25.3.1'
複製代碼
與Vector
相關的兩個包爲:
gradle
配置文件若是**gradle
的版本小於2.0
**:
android {
defaultConfig {
generatedDensities = []
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
複製代碼
若是**gradle
的版本大於2.0
**,例如咱們所用的版本:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
}
}
複製代碼
那麼須要這樣配置:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
複製代碼
關於更多兼容性的問題,能夠查看下面這篇文章
VectorDrawable
若是使用靜態的方式展現VectorDrawable
,那麼很簡單,只須要像使用普通的drawable
同樣,首先,咱們按照第三節的方法,獲取到一個vectorDrawable
,並把它放在drawable
文件夾下:
<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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
複製代碼
咱們能夠應用於:
ImageView
的src
View
的background
TextView
的drawable
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/iv_static"
android:layout_width="50dp"
android:layout_height="50dp"
android:clickable="true"
android:src="@drawable/ic_account_circle_selector"/>
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:clickable="true"
android:background="@drawable/ic_account_circle_selector"/>
<TextView
android:drawableStart="@drawable/ic_account_circle_black_24dp"
android:text="UserName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
複製代碼
在上面的例子中,咱們還使用了ic_account_circle_selector
,其定義以下:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_account_circle_black_24dp" android:state_pressed="true"/>
<item android:drawable="@drawable/ic_account_circle_black_normal_24dp"/>
</selector>
複製代碼
ic_account_circle_black_24dp
就是以前獲取到的素材,而ic_account_circle_black_normal_24dp
就是改變了它的fillColor
屬性:
<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="#80000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</vector>
複製代碼
點擊後的效果爲:
VectorDrawable
動態的VectorDrawable
,也就是AnimatedVectorDrawable
,通常來講,它的整個結構以下圖所示:
VectorDrawable
,通常須要提供三種類型的
*.xml
文件,這三個
xml
文件的根標籤分別爲:
vector
:圖像資源,也就是咱們上面討論的靜態vector
,定義於res/drawable
文件夾下。objectAnimator
:定義圖像資源中個元素的動畫行爲,定義於res/anim
文件夾下。animated - vector
:對vector
中的元素與objectAnimator
進行組合,定義於res/drawable
文件夾下。<group>
標籤進行動畫下面,咱們先看一個簡單的例子,上面咱們所談到的三個*.xml
文件以下:
vector
文件<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<group android:name="group_account" android:pivotX="12" android:pivotY="12">
<path
android:fillColor="#FF000000"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,5c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM12,19.2c-2.5,0 -4.71,-1.28 -6,-3.22 0.03,-1.99 4,-3.08 6,-3.08 1.99,0 5.97,1.09 6,3.08 -1.29,1.94 -3.5,3.22 -6,3.22z"/>
</group>
</vector>
複製代碼
這裏咱們生成了一個頭像的Vector
素材,它的圖像以下,注意到,咱們用一個group
標籤把path
標籤包裹起來,而且給它定義了一個name
屬性爲group_account
,這個屬性在後面會用到。
objectAnimator
文件<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="500"
android:propertyName="rotation"
android:repeatCount="infinite"
android:valueFrom="0"
android:valueTo="360"/>
</set>
複製代碼
objectAnimator
的定義和屬性動畫是相同的,咱們須要指定須要變換的屬性,也就是propertyName
,並經過valueFrom/valueTo
指定變化的起點值和終點值,這裏咱們選擇了採用無限循環的方式來變換目標的rotation
屬性。
animated-vector
文件<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/account_vector">
<target
android:animation="@anim/account_object_animator"
android:name="group_account"/>
</animated-vector>
複製代碼
animated-vector
和vector
是一一對應的關係,所以須要在根標籤中指定android:drawable
,也就是在7.1.1
中的vector
文件。 而每個target
標籤是內是成對的name - animation
屬性,name
就是在7.1.1
中聲明的group
的name
,而animation
則是在7.1.2
中定義的動畫文件。
若是objectAnimator
所指定的屬性在name
所對應的標籤中沒有,那麼不會發生任何變化。
首先,在佈局的xml
文件中,把imageView
的src
指定爲7.1.3
中的animate-vector
:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_horizontal">
<ImageView
android:id="@+id/iv_dynamic"
android:src="@drawable/account_animated_vector"
android:text="UserName"
android:layout_width="50dp"
android:layout_height="50dp"/>
</LinearLayout>
複製代碼
在代碼中,須要手動得到這個vectorDrawable
,而後啓動動畫:
public class VectorDrawableActivity extends AppCompatActivity {
private ImageView mAnimateView;
private AnimatedVectorDrawable mAnimatedVectorDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vector_drawable);
mAnimateView = (ImageView) findViewById(R.id.iv_dynamic);
mAnimatedVectorDrawable = (AnimatedVectorDrawable) mAnimateView.getDrawable();
mAnimateView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAnimatedVectorDrawable.start();
}
});
}
}
複製代碼
效果以下:
<path>
標籤中的屬性進行動畫在7.1
中,演示瞭如何對group
標籤的屬性進行變換,下面,咱們再演示一下如何對path
標籤中的屬性進行變換。和前面相似,咱們依然須要三種類性的*.xml
文件
vector
文件<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:name="path_check"
android:fillColor="#FF000000"
android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>
複製代碼
這裏,一樣須要給path
指定一個名字,用於後面和objectAnimator
進行關聯,它的素材爲:
objectAnimator
文件<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="500"
android:propertyName="trimPathEnd"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"/>
</set>
複製代碼
這裏,咱們選擇的是path
標籤下的trimPathEnd
屬性,它表示從Path
終點的位置去除Path
,與之對應的還有trimPathStart
屬性,它表示從Path
起點的位置去除Path
,而trimPathOffset
則能夠改變Path
的起點,這三個值的取值範圍都是0~1
。
animated-vector
文件<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/check_vector">
<target
android:animation="@anim/check_object_animator"
android:name="path_check"/>
</animated-vector>
複製代碼
效果以下:
<path>
之間切換除了上面普通的屬性以外,還支持對<path>
標籤下的<pathData>
進行改變,系統會比較兩個pathData
之間的差異,並自動產生合適的動畫。須要注意,它要求這兩個pathData
的點座標的個數是相同的。
Vector
文件這裏,咱們須要生成兩個vectorDrawable
,首先是起始的VectorDrawable
:
<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:name="path_arrow_down"
android:fillColor="#FF000000"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>
複製代碼
它的素材爲:
VectorDrawable
:
<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="M7,14l5,-5 5,5z"/>
</vector>
複製代碼
它對應的素材爲:
objectAnimator
文件<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="500"
android:propertyName="pathData"
android:valueFrom="M7,10l5,5 5,-5z"
android:valueTo="M7,14l5,-5 5,5z"
android:valueType="pathType"/>
</set>
複製代碼
這裏的propertyName
和valueType
須要分別定義爲pathData
和pathType
,而起點和終點的值就是咱們在7.3.1
生成的兩個VectorDrawable
所對應的pathData
屬性的值。
animated-vector
文件<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/arrow_down_vector">
<target
android:animation="@anim/arrow_down_object_animator"
android:name="path_arrow_down"/>
</animated-vector>
複製代碼
最終的效果爲:
VectorDrawable
的性能關於VectorDrawable
的性能問題,Android Vector 曲折的兼容之路 這篇文章說的很好,所以直接引用過來了:
Bitmap
的繪製效率並不必定會比Vector
高,它們有必定的平衡點,當Vector
比較簡單時,其效率是必定比Bitmap
高的,因此,爲了保證Vector
的高效率,Vector
須要更加簡單,PathData
更加標準、精簡,當Vector
圖像變得很是複雜時,就須要使用Bitmap
來代替了。
Vector
適用於ICON
、Button
、ImageView
的圖標等小的ICON
,或者是須要的動畫效果,因爲Bitmap
在GPU
中有緩存功能,而Vector
並無,因此Vector
圖像不能作頻繁的重繪Vector
圖像過於複雜時,不只僅要注意繪製效率,初始化效率也是須要考慮的重要因素SVG
加載速度會快於PNG
,但渲染速度會慢於PNG
,畢竟PNG
有硬件加速,但平均下來,加載速度的提高彌補了繪製的速度缺陷。1. Android Vector 曲折的兼容之路 2. VectorDrawable 怎麼玩 3. Android 使用矢量圖(SVG, VectorDrawable)實踐篇 4. SVG - 百度百科 5. Android 中的 SVG 圖像的各個屬性意義