前言
Android技能書系列:
Android基礎知識
Android技能樹 — Android儲存路徑及IO操作小結
資料結構基礎知識
演算法基礎知識
先上腦圖:


Drawable

固有高/寬 & 大小

我們知道平常使用最多的Drawable可能是圖片了,我們知道一個圖片的原本的尺寸,比如下面這個圖:


大小為64X64,我們把它賦值給一個ImageView做為背景,同時這個ImageView設定的寬高都很大:
<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@drawable/back"/>
複製程式碼

我們可以看到我們的圖片實際上變的很大,所以最終的圖片大小不一定是它固有寬/高。
所以對於這個圖片,它的固有高/寬是它原本圖片的大小,而實際上當最為我們ImageView的背景後,被拉伸至於View同等大小了。而且對於一些我們自己畫的Drawable,不像圖片那樣,有自己原本的尺寸,比如我們自己寫了個一個紅色的Drawable,這時候它沒有固定的尺寸,所以getIntrinsicWidth/height
會返回-1。

Drawable分類

單個Drawable

BitmapDrawable:

這裡特別講一下平鋪模式,比如還是上面那個箭頭的圖片,我們寫相應BitmapDrawable程式碼:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/back"
android:tileMode="repeat"
>
</bitmap>
複製程式碼
<ImageView
android:id="@+id/logo"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@drawable/bitmapdrawable"/>
複製程式碼

這裡有一點要注意:記住是賦給android:background
,有些人寫習慣了,可能就賦給了ImageView
的android:src
屬性, 然後就不會有效果了。
ShapeDrawable

我們主要注意這幾點:
- 當我們對描邊進行設定虛線時候,android:dashWidth和android:dashGap只要有一個為0,虛線效果將不能生效。 比如:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<stroke android:color="@color/colorBlack"
android:width="2dp"
android:dashGap="30dp"
android:dashWidth="40dp"/>
</shape>
複製程式碼
我們可以看到效果是:


- 標籤的設定: 定義內容離邊界的距離,有些人說我設定了Padding,可是沒有看出效果來,比如下面:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<stroke android:color="@color/colorBlack"
android:width="2dp"
android:dashGap="0dp"
android:dashWidth="40dp"/>
<padding android:left="130dp"
/>
<solid android:color="@color/warning_stroke_color"/>
</shape>
複製程式碼

<ImageView
android:id="@+id/logo"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@drawable/bg"/>
複製程式碼

然後我們會發現,what啥都沒變啊。其實我們要知道是內容離邊界的距離。比如我們這裡換成TextView就知道了:
<TextView
android:id="@+id/logo"
android:layout_width="300dp"
android:layout_height="300dp"
android:text="aaaaaaaaaaaaaaaaaaaa"
android:background="@drawable/sdf"/>
複製程式碼

- 標籤的作用:
我們知道圖片的話,有自己的固有寬/高,但是像這種ShapeBitmap,沒有固有寬/高,
getIntrinsicWidth/height
獲取到的是-1,所以我們如果設定了標籤,獲取到的就是你設定的值了。
<size
android:width="100dp"
android:height="100dp"/>
複製程式碼
InsetDrawable:

可以把其他的Drawable內嵌到自己裡面,然後在可以設定四周的距離。
比如我們有時候在狀態列處,點選返回按鈕,但是美工切圖的返回鍵有點小,直接設定進去,有時候使用者按返回鍵會按不到,一種是把ImageView
的寬高設定的大一點,另外一種可以使用這個InsetDrawable
。
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/back"
android:insetLeft="20dp"
android:insetTop="20dp"
android:insetRight="20dp"
android:insetBottom="20dp"
>
</inset>
複製程式碼
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/insetdrawable"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/back"
/>
複製程式碼
我們可以檢視設定了InsetDrawable
和直接設定返回按鈕圖片的樣子:

ScaleDrawable:

可以縮放的Drawable,效果如下:

具體的使用可以參考這篇文章:Android Drawable - Scale Drawable使用詳解
ClipDrawable:

可裁剪的Drawable,效果如下:

具體的使用可以參考這篇文章:ClipDrawable讓開發變得更簡單

Drawable集合

Drawable集合的意思是這些Drawable可以放多個Drawable,比如可以放多個圖片資源在裡面。
LayerDrawable

它是一種層次化的Drawable集合,通過不同的Drawable放置在不同的層上面達到了疊加後的效果。並且下面的item覆蓋上面的item。

比如這個圖片上的搜尋框:

我們可以使用LayerDrawable來實現,只需要把中間的放大鏡和文字變成一個圖片,比如

然後背景為:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<solid android:color="@color/colorWhite"/>
</shape>
複製程式碼

最後使用LayerDrawable:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/search_bg"/>
<item android:drawable="@drawable/search"
android:right="60dp"
android:left="60dp"
android:top="10dp"
android:bottom="10dp"
/>
</layer-list>
複製程式碼
效果圖為:

具體可以參考以下文章:
Android Drawable - Layer Drawable使用詳解
layer-list -- layer-list的基本使用介紹
StateListDrawable

這個估計是大家用的最多的,通常用在不同的按鈕上,當按下是什麼背景,送開的時候是什麼背景,當處於不可點選的時候是什麼背景。

這個我就不多說了,可以參考這篇:Drawable子類之——StateListDrawable (選擇器)
這裡額外說一個注意點: 系統根據View狀態從selector中按照從上到下的順序查詢選擇對應item,所以預設的item放在最後一條,這樣上面都不符合時候,會匹配上預設的item,因為預設的item不附帶狀態,可以匹配View的任何狀態
LevelListDrawable

這個有點像StateListDrawable,在不同Level下會使用不同的圖,不同的是,它是根據每個item設定的Level範圍來確定的。
TransitionDrawable

主要是用來實現二個Drawable之間的淡入淡出,很容易就想到了animation動畫來實現,但是發現使用動畫的話,但是在呼叫statAnimation的時候因為圖片已經顯示了,再播放一次動畫其實會導致細微的閃爍效果。所以可以使用TransitionDrawable來實現。
如下效果:

具體可以參考文章:[如何使用TransitionDrawable實現背景切換漸變效果 ](blog.csdn.net/u011043551/…)
結語
其實都是很基礎的東西。但是就當自己做個總結了。
PS:這塊的Drawable內容參考《Android 開發藝術探索》。