
相信你已經看到了app23.2的支持庫的更新日志了,現在在支持庫中已經兼容了矢量圖:VectorDrawableCompat和Animated VectorDrawableCompat
它被實現成了一個獨立的功能模塊。眾所周知:開發者想使用資源圖片,我們已經把支持矢量圖繪制添加到了APP中。
一下是幾個整合的原因,包括:
- 允許開發者在所有的Android2.1以上的設備更早的用上<Vecotrs>圖
- 允許APP本身能夠用矢量圖。它本身已經減少了APP AAR的70KB左右。這聽起來不算很大,但是對于設備來說節省是很重要的。快速的節省是為了存儲和傳輸。
*首先
VectorDrawableCompat依賴與AAPT的一些功能,它能保持最近矢量圖使用的添加的屬性ID,以便他們可以被v21之前的引用。
如果你沒有啟用這個標志,當你在KitKat上運行你的APP你會看到以下(或者類似)錯誤:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable-v19/abc_ic_ab_back_material.xml from drawable resource ID #0x7f020016
at android.content.res.Resources.loadDrawable(Resources.java:2097)
at android.content.res.Resources.getDrawable(Resources.java:700)
...
啟用標志位
我猜你們中的大多數都正在用Gradle。
如果你正在用Gradle插件v2.0或者更高,我有一個簡潔方法去啟用它:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
如果你還沒有更新,在用v1.5后者更低的版本,你需要在你的build.gradle文件里添加以下內容:
android {
defaultConfig {
// Stops the Gradle plugin’s automatic rasterization of vectors
generatedDensities = []
}
// Flag to tell aapt to keep the attribute ids around
aaptOptions {
additionalParameters "--no-version-vectors"
}
}
怎么在項目中用我自己的矢量圖資源?
在我們開始之前應該做一些準備。當我們在用AppCompat時,VectorDrawableCompat不僅用在Api20或者更低。這意味著你當你在Api21或者更高時你在用framework層的VectorDrawable類。在用api21+的framework create()方法是不同的,是一個代理項目。
所以如果你的minSdkVersion<21而且你想在你的APP中用一個矢量資源的時候,首先你應該檢查這個資源應該用在api21+的設備上,只是為了一個全面的檢查。
起作用之后,我們該怎么用?
在api7+有兩種使用矢量圖的方法:
- AppCompatImageView
AppCompat的“injects”代替了許多框架中的組件。我們已經加入了app:srcCompat屬性去支持VectorDrawableCompat。它代替了android:src屬性,并且你也可以安全的使用那些不屬于矢量圖的資源。下面是一個我們已經用過的矢量圖的例子:
res/drawable/ic_search.xml
<vector xmlns:android="..."
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:pathData="..."
android:fillColor="@android:color/white"/>
</vector>
一個ImageView的聲明:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_search"/>
你也可以這樣設置它:
ImageView iv = (ImageView) findViewById(...);
iv.setImageResource(R.drawable.ic_search);
這樣和ImageButton相同的用法。
“魔法方式”
AppCompat能夠攔截一些圖片引用,你在工作的時候能夠用所有的標準的屬性,每一個都會工作。
讓我告訴你工作什么:
其中引用只包含一個矢量資源等資源可繪容器可繪制。
例如,一個StateListDrawable它引用其中包含的載體的其他文件。
res/drawable/state_list_icon.xml
<selector xmlns:android="...">
<item android:state_checked="true"
android:drawable="@drawable/checked_icon" />
<item android:drawable="@drawable/icon" />
</selector>
res/drawable/checked_icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:viewportWidth="32"
android:height="32dp"
android:viewportHeight="32">
...
</vector>
作為一個TextView的復合圖:
<TextView
android:drawableLeft="@drawable/state_list_icon" />
作為一個RadioButton的背景圖:
<RadioButton
android:button="@drawable/state_list_icon" />
作為一個ImageView的背景圖:
<ImageView
android:src="@drawable/state_list_icon" />
你不得不去用StateListDrawable,它也和InsetDrawable,LayerDrawable,LevelListDrawable,RotateDrawable容器一起工作。規則僅僅是矢量圖需要在一個分離的文件中。
矢量動畫是什么?
到目前為止我們僅僅討論了“static”的矢量圖,所以讓我們談談矢量動畫。他們用同樣的方式工作,但是他們僅僅在api 11+可用。如果你嘗試在api 10或者更低去用矢量動畫,你會得到一個"null"或者什么都不顯示。
下面是一些矢量圖能夠運行在小于api 21平臺下的限制:
- Path Morphing (PathType evaluator)
- 路徑攔截。被用于代替系統定義的類似LinearInterpolator的攔截器
- 沿路徑移動。很少備用,這可以左右移動,沿著任何路徑。
總之,動畫的聲明已經可用,并且這個功能是基于你平臺運行的APP。
“魔法方式”怎么工作?
如果對它的實現不感興趣你可以跳過這段。
目前沒有方法在Android平臺使用從資源的自定義繪制的實現,所以下面這樣是不可以的:
res/drawable/my_awesome_drawable.xml
<my.package.SuperAwesomeDrawable xmlns:app="..."
app:customAttr1="32dp"
app:customAttr2="32dp">
...
</my.package.SuperAwesomeDrawable>
為了迭代:之前的代碼在當前是不可以的
所以你可能會問普通的drawable是怎么工作的?當你設置一個resource的屬性時,manifest本身會作為一個TypedArray去實現View,Drawable,etc,去調用obtainStyledAttributes()方法。
下面是一個InsetDrawable的例子:
Resources r = ...;
int drawableRes =
a.getResourceId(android.R.styleable.InsetDrawable_drawable, 0);
if (drawableRes != 0) {
dr = r.getDrawable(drawableRes);
}
有趣么?正如我說的,這是所有的實現細節所以不要擔心不不理解。