本章介紹了常用的 XML drawable,包括 shape,state list 和 layer list。還介紹了 9-patch 圖檔和 mipmap 目錄等知識。
GitHub 位址:
完成第21章
1. XML drawable
在 Android 世界裡,凡是要在螢幕上繪制的東西都可以叫作 drawable,比如抽象圖形、 Drawable 類的子類、位圖圖像等。我們之前用來封裝圖檔的 BitmapDrawable 就是一種 drawable。 本章我們使用的 drawable 都定義在 XML 檔案中,可以歸為一類,統稱為 XML drawable。
1.1 為什麼要使用 XML drawable
XML drawable 用起來友善靈活,不僅用法多樣,還易于更新維護。搭配使用 shape drawable
和 layer list drawable 可以做出複雜的背景圖,連圖像編輯器都省了。更改應用的配色更是簡單,直接修改 XML drawable 中的顔色就行了。
另外,XML drawable 獨立于螢幕像素密度,它們直接定義在 drawable 目錄中,不需要加螢幕密度資源修飾符。如果是普通圖像,就需要準備多個版本,以适配不同螢幕像素密度的裝置;而 XML drawable 隻要定義一次,就能在任何裝置的螢幕上表現出色。
1.2 shape drawable
一個常見的圓形 shape drawable 如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="@color/red"/>
<stroke
android:width="4dp"
android:color="@color/dark_red"/>
</shape>
該 shape drawable 定義了一個帶有暗紅色圓環的填充紅色的橢圓。
- shape 标簽中 android:shape 屬性定義了其形狀為橢圓(當然,如果需要是正圓,隻需要把控件的高寬設為相等即可),還可以是長方形,線條,梯形等圖形;
- solid 标簽定義填充,其中 android:color 定義其填充顔色(預設透明)
- stroke 标簽定義邊框,屬性都類似
- 還有更多标簽和屬性,可以在這裡找到:shape drawable
1.3 state list drawable
為了在控件的不同狀态下切換不同的 drawable, 我們用到了 state list drawable,它會根據按鈕的狀态改變使用的 drawable,一個例子如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_beat_box_pressed"
android:state_pressed="true"/>
<item android:drawable="@drawable/button_beat_box_normal"/>
</selector>
将一個 drawable 資源檔案定義為 selector,便是讓系統根據狀态選擇。狀态有按下,禁用,聚焦以及激活等狀态,可以根據不同的狀态使用不同的 drawable。
還有更多标簽和屬性,可以在這裡找到:state list drawable
1.4 layer list drawable
layer list 可以将多個 drawable 組成一個 drawable 并可以指定其擺放層次和位置,可以組成一些複雜的效果。
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid
android:color="@color/red"/>
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke
android:width="4dp"
android:color="@color/dark_red"/>
</shape>
</item>
</layer-list>
這個 layer list 将一個矩形疊放在一個橢圓上。還有更多的屬性可以檢視 layer list drawable
2. 9-patch 圖像(九宮格圖像)
有時候,按鈕背景圖必須用到普通圖檔。那麼,如果按鈕需要以不同尺寸顯示,背景圖該如何變化呢?如果按鈕的寬度大于背景圖的寬度,圖檔會被拉伸。拉伸的圖檔會有很好的效果嗎? 朝一個方向拉伸背景圖很可能會讓圖檔失去原樣,是以得想個辦法控制圖檔拉伸方式。
9-patch 就是這樣一種方式,它将圖像分成3×3的網格,即由9 patch 組成的網格。網格角落部分不會被縮放,邊緣部分的4個 patch 隻按一個次元縮放,而中間部分則按兩個次元縮放,如下圖:
9-patch 圖像和普通 PNG 圖像十分相似,隻有兩處不同:9-patch 圖像檔案名以.9.png 結尾,圖像邊緣具有1像素寬度的邊框。這個邊框用以指定9-patch 圖像的中間位置。邊框像素繪制為黑線, 以表明中間位置,邊緣部分則用透明色表示。
在 Android Studio 中,右鍵單擊想要轉換為 9-patch 的圖像檔案選擇建立 9-patch 檔案,然後輕按兩下打開,畫上黑邊即可。旁邊會顯示不同方向拉伸後的效果。
3. mipmap 目錄
應用要用到圖像,就一般會針對不同的裝置尺寸準備不同尺寸的圖檔,再分别放入 drawable-mdpi 和 drawable-hdpi 這樣的檔案夾。然後,按名字引用它們。 剩下的就交給 Android 了,它會根據目前裝置的螢幕密度調用相應的圖檔。
這樣就會存在一個問題:釋出出去的 APK 檔案包含了項目 drawable 目錄裡的所有圖檔,哪怕是從來不會用到的圖檔,這會讓應用體積無意義地增大。為減輕負擔,有人想到針對裝置定制 APK,比如 mdpi APK 一個,hdpi APK 一個,等等。有關 APK 分包的詳細資訊,可參閱Build Multiple APKs
相反,設定分包以後,有的時候會需要不同分辨率的圖示,比如啟動器不同,需要的圖示清晰度不同,是以,要用到 mipmap 目錄。APK 分包時,mipmap 資源會全部包含在 APK 檔案中。