Android中Drawable分類彙總(上)
阿新 • • 發佈:2019-02-15
Android把可繪製的物件抽象為Drawable,不同的圖形影象資源就代表著不同的drawable型別。Android FrameWork提供了一些具體的Drawable實現,通常在程式碼中都不會直接接觸Drawable的實現類。
在實際的開發過程中,會把使用到的資源都放置在res/drawable目錄,剩下的工作交給Android SDK 就行了,當需要使用圖片資源的時候,可以使用@drawable標誌在xml中引用drawable資源就行,也可以在程式碼中使用id引用這些drawable資源。
在使用drawable資源的時,有一點需要注意,drawable預設是記憶體共享的,也就說在不同的地方使用了同一個drawable,它們都指向相同的資源,而且具有相同的狀態,如果在一個地方修改了這個drawable,所有使用它的地方都會改變。
Android內建瞭如下幾種Drawable型別:ColorDrawable、GradientDrawable、BitmapDrawable、 NinePatchDrawable、InsetDrawable、ClipDrawable、ScaleDrawable、RotateDrawable、AnimationDrawable、LayerDrawable、LevelListDrawable、StateListDrawable、TransitionDrawable。
除了這些預置的drawable實現類以外,也可以自定義drawable的實現型別,大部分情況都不需要自定義drawable型別,使用系統提供的這些drawable實現型別已經覆蓋了很多情況。在實際的程式設計過程中也很少會接觸這些具體drawable實現型別,因為編寫android應用程式使用xml可以很容易的建立drawable,只有在程式中需要修改drawable的屬性時,才需要使用具體的drawable型別提供的方法來處理。下面就來逐個認識這些Drawable型別。
一、ColorDrawable
ColorDrawable 是最簡單的Drawable,它實際上是代表了單色可繪製區域,它包裝了一種固定的顏色,當ColorDrawable被繪製到畫布的時候會使用顏色填充Paint,在畫布上繪製一塊單色的區域。
在xml檔案中使用color作為根節點來建立ColorDrawable,它只有一個android:color屬性,通過它來決定ColorDrawable的顏色,Android並沒有提供修改這個顏色值的Api,所以這個顏色一旦設定之後,就不能直接修改了。
下面的xml檔案定義了一個顏色為紅色的ColorDrawable:
當然也可以使用Java程式碼建立ColorDrawable,需要注意的是Android中使用一個int型別的資料表示顏色值,通常習慣使用十六進位制格式的資料表示顏色值。一個int型別包含四個位元組,分別代表顏色的4個組成部分:透明度(Alpha)、紅(RED)、綠(GREEN)、藍(BLUE),每個部分由一個位元組(8個bit)表示,取值範圍為0~255。在xml中使用顏色時可以省略透明度(Alpha)部分,如#ff0000表示紅色。但是在程式碼中必須要明確指出透明度(Alpha)代表的資料,如果省略了就表示完全透明的顏色,例如0xFFFF0000表示紅色,而0xFF0000雖然也表示紅色,但它卻是完全透明的,也就是說當繪製到畫布上時,看不出有任何效果。
使用Java程式碼也可以建立ColorDrawable,程式碼如下:
二、GradientDrawable
GradientDrawable 表示一個漸變區域,可以實現線性漸變、發散漸變和平鋪漸變效果,在Android中可以使用GradientDrawable表示很多複雜而又絢麗的介面效果。
可以使用xml定義GradientDrawable,相對於ColorDrawable型別,GradientDrawable要複雜很多,它有很多的元素組成。在xml檔案中使用shape作為根節點來建立GradientDrawable,它包含很多屬性和子節點,下面是GradientDrawable的xml文件節點結構。
其中每個節點都有許多屬性需要設定,以達到不同的漸變效果。
以下是幾種不同漸變效果實現的xml檔案程式碼:
以下幾幅圖展示了上述三個漸變效果:
圖6-1 線性漸變效果的橢圓
圖6-2 平鋪漸變效果的圓環
圖6-3 發散漸變效果的圓
三、BitmapDrawable
BitmapDrawable 是對bitmap的一種包裝,可以設定它包裝的bitmap在BitmapDrawable區域內的繪製方式,如平鋪填充、拉伸填充或者保持圖片原始大小,也可以在BitmapDrawable區域內部使用gravity指定的對齊方式。
在xml檔案中使用bitmap作為根節點來定義BitmapDrawable。
下面的xml程式碼定義一個BitmapDrawable,同時設定了BitmapDrawable的tileMode 屬性為mirror,通過這樣設定會使用小圖片在水平和豎直方向做鏡面平鋪效果。
也可以使用Java程式碼實現相同的效果,等價的Java程式碼如下:
效果如下圖所示:
圖6-4 BitmapDrawable執行效果圖
四、NinePatchDrawable
NinePatchDrawable,“點九圖”是Andriod平臺的一種特殊的圖片格式,副檔名為:.9.png。支援Android平臺的手機型別很多,有多種不同的解析度,很多控制元件的切圖檔案在被放大拉伸後,邊角會模糊失真。在android平臺下使用“點九”圖片處理技術,可以將圖片橫向和縱向同時進行拉伸,以實現在多解析度下的完美顯示效果。點九圖片在拉伸時仍能保留影象的漸變質感和圓角的精細度。
Android SDK工具集提供了處理點九圖片的工具,可以通過draw9patch.bat執行,通過這個工具可以很容易把普通的PNG圖片處理成“點九”圖片。從它的名字也很容易理解“點九”圖的含義,其實相當於把一張PNG圖分成了9個部分(九宮格),分別為4個角,4條邊,以及一箇中間區域,4個角是不做拉伸的,所以還能一直保持圓角的清晰狀態,而2條水平邊和2條垂直邊分別只做水平和垂直拉伸,所以不會出現邊框被拉粗的情況,只有中間用黑線指定的區域做拉伸,通過這種處理方式圖片才不會失真。如圖6-5所示,對4條黑線分別做了註釋。左邊和上邊的黑線形成的矩形區域是圖片的拉伸區域,下邊和右邊形成的矩形區域是內容所在的區域。黑線可以是連續的也可以是不連續的,不過為了達到最好的顯示效果,最好使用連續的黑線。
圖6-5 點九圖片示意圖
使用了*.9.png圖片技術後,只需要採用一套介面切圖去適配不同的解析度,而且大幅減少安裝包的大小。Android FrameWork在顯示點九圖片時使用了高效的優化演算法,所示應用程式不需要專門做處理就可以實現圖片拉伸自適應,減少了程式碼量和實際開發的工作量。
在xml檔案中使用使用nine-patch作為根節點建立NinePatchDrawable。同時,也可以使用bitmap包裝點九圖片,android FrameWork會根據android:src屬性設定的圖片型別來生成對應的drawable。程式碼如下:
下面看一下原始點九圖片以及拉伸之後的效果:
圖6-6 原始點九圖片
圖6-7 點九圖片拉伸之後的效果
最後,需要指出的是,Android雖然可以使用Java程式碼建立NinePatchDrawable,但是極少情況會那麼做,主要的原因是由於Android SDK會在編譯工程時對點九圖片進行編譯,形成特殊格式的圖片。使用程式碼建立NinePatchDrawable時只能針對編譯過的點九圖片資源,對於沒有編譯過的點九圖片資源都當做BitmapDrawable對待。在使用點九圖片時需要注意的是,點九圖只能適用於拉伸的情況,對於壓縮的情況並不適用,如果需要適配很多解析度的螢幕時需要把點九圖做的小一點。
五、InsetDrawable
InsetDrawable 表示一個drawable嵌入到另外一個drawable內部,並且在內部留一些間距,這一點很像drawable的padding屬性,區別在於 padding表示drawable的內容與drawable本身的邊距,insetDrawable表示兩個drawable和容器之間的邊距。當控制元件需要的背景比實際的邊框小的時候比較適合使用InsetDrawable。
在xml檔案中使用inset作為跟節點定義InsetDrawable。
下面的xml定義了一個四邊邊距都為20dip的InsetDrawable,程式碼如下:
效果如下圖所示:
圖6-8 InsetDrawable執行效果圖
六、ClipDrawable
ClipDrawable 是對一個Drawable進行剪下操作,可以控制這個drawable的剪下區域,以及相相對於容器的對齊方式,android中的進度條就是使用一個ClipDrawable實現效果的,它根據level的屬性值,決定剪下區域的大小。
在xml檔案中使用clip作為根節點定義ClipDrawable。
需要注意的是ClipDrawable是根據level的大小控制圖片剪下操作的,官方文件的note中提到:The drawable is clipped completely and not visible when the level is 0 and fully revealed when the level is 10,000。也就是level的大小從0到10000,level為0時完全不顯示,為10000時完全顯示。是用Drawable提供的setLevel(int level)方法來設定剪下區域。
下面為定義ClipDrawable的程式碼:
如果沒有android:drawable屬性,必須要設定一個任意型別的drawable作為子節點,程式碼如下:
效果如下圖所示:
圖6-9 ClipDrawable執行效果圖
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< color
xmlns:android = "http://schemas.android.com/apk/res/android" |
3 |
android:color = "#FF0000"
/> |
[程式碼]java程式碼:
1 |
ColorDrawable drawable = new
ColorDrawable( 0xffff0000 ); |
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< shape
xmlns:android = "http://schemas.android.com/apk/res/android" >
|
3 |
< size
/> //定義區域的大小 |
4 |
< gradient >//設定區域背景的漸變效果
|
5 |
< solid />//設定區域的背景顏色,如果設定了solid會覆蓋gradient的效果
|
6 |
< stroke
/>//設定區域的邊框效果 |
7 |
< padding
/>//設定區域的內邊距 |
8 |
</ shape > |
[程式碼]xml程式碼:
01 |
<!-- 線性漸變效果的橢圓--> |
02 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
03 |
< shape |
04 |
xmlns:android = "http://schemas.android.com/apk/res/android" |
05 |
android:shape = "oval" >
|
06 |
07 |
< gradient |
08 |
android:startColor = "#ff0000" |
09 |
android:centerColor = "#00ff00" |
10 |
android:endColor = "#0000ff" |
11 |
android:angle = "90"
/> |
12 |
< stroke |
13 |
android:width = "3dip" |
14 |
android:color = "#fff" |
15 |
android:dashWidth = "4dip" |
16 |
android:dashGap = "5dip"
/> |
17 |
</ shape >
|
18 |
19 |
<!-- 平鋪漸變效果的圓環--> |
20 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
21 |
< shape
xmlns:android = "http://schemas.android.com/apk/res/android" |
22 |
android:shape = "ring"
android:innerRadiusRatio = "8" |
23 |
android:thicknessRatio = "3"
android:useLevel = "false" >
|
24 |
< gradient
android:type = "sweep"
android:useLevel = "false" |
25 |
android:startColor = "#ff0000"
android:endColor = "#0000ff"
android:centerColor = "#00ff00" />
|
26 |
</ shape >
|
27 |
28 |
<!-- 發散漸變效果的圓--> |
29 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
30 |
< shape
xmlns:android = "http://schemas.android.com/apk/res/android" |
31 |
android:shape = "ring"
android:innerRadius = "0dip" |
32 |
android:thickness = "70dip"
android:useLevel = "false" >
|
33 |
< gradient
android:type = "radial"
android:useLevel = "false"
android:gradientRadius = "70" |
34 |
android:startColor = "#ff0000"
android:endColor = "#0000ff"
android:centerColor = "#00ff00" />
|
35 |
</ shape > |
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< bitmap
xmlns:android = "http://schemas.android.com/apk/res/android" |
3 |
android:src = "@drawable/png_icon_416" |
4 |
android:tileMode = "mirror" |
5 |
android:antialias = "true" |
6 |
android:dither = "true" |
7 |
>
|
8 |
</ bitmap > |
[程式碼]java程式碼:
1 |
Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.png_icon_416);
|
2 |
BitmapDrawable mBitmapDrawable =
new BitmapDrawable(mBitmap);
|
3 |
mBitmapDrawable.setTileModeXY(TileMode.MIRROR, TileMode.MIRROR);
|
4 |
mBitmapDrawable.setAntiAlias( true );
|
5 |
mBitmapDrawable.setDither( true );
|
6 |
mDrawable = mBitmapDrawable; |
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< nine-patch |
3 |
xmlns:android = "http://schemas.android.com/apk/res/android" |
4 |
android:src = "@drawable/droid_logo" |
5 |
android:dither = "true"
/> |
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< bitamp |
3 |
xmlns:android = "http://schemas.android.com/apk/res/android" |
4 |
android:src = "@drawable/droid_logo" |
5 |
android:dither = "true"
/> |
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< inset
xmlns:android = "http://schemas.android.com/apk/res/android" |
3 |
android:drawable = "@drawable/bitmap_bell" |
4 |
android:insetLeft = "20dp" |
5 |
android:insetRight = "20dp" |
6 |
android:insetTop = "20dp" |
7 |
android:insetBottom = "20dp" |
8 |
>
|
9 |
</ inset > |
[程式碼]xml程式碼:
1 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
2 |
< clip
xmlns:android = "http://schemas.android.com/apk/res/android" |
3 |
android:clipOrientation = "horizontal" |
4 |
android:drawable = "@drawable/bitmap_android" |
5 |
android:gravity = "left" |
6 |
>
|
7 |
</ clip > |
[程式碼]xml程式碼:
01 |
<? xml
version = "1.0"
encoding = "utf-8" ?>
|
02 |
< clip
xmlns:android = "http://schemas.android.com/apk/res/android" |
03 |
android:clipOrientation = "horizontal" |
04 |
android:gravity = "left" |
05 |
>
|
06 |
< bitmap |
07 |
android:src = "@drawable/android_text" |
08 |
android:gravity = "center" |
09 |
/>
|
10 |
</ clip > |