Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android——Drawable

Android——Drawable

編輯:關於Android編程

主要介紹內容:

BitmapDrawable ShapeDrawable LayerDrawable StateListDrawable LevelListDrawable TransitionDrawable InsetDrawable ScaleDrawable ClipDrawable

在進入真正的介紹之前,我們先來簡單的了解下 Drawable。所謂的 Drawable 其實表示的是一種可以在 Canvas 上進行繪制的抽象的概念,它的種類有很多,最常見的顏色和圖片都可以是一個 Drawable。它的使用非常簡單,比之前我們介紹的自定義 View 的成本要低;其次,非圖片類型的 Drawable 占用空間較小,這對減小 apk 的大小也很有幫助。

一般在實際開發中, Drawable 常被用來作為 View 的背景使用。Drawable 一遍都是通過 XML 來定義的,當然我們也可以通過代碼來創建具體的 Drawable 對象,只是用代碼來創建會稍顯復雜。在 Android 的設計中, Drawable 是一個抽象類,它是所有 Drawable 對象的基類,每個具體的 Drawable 都是它的子類,比如 shapeDrawable、BitmapDrawable等,Drawable 的層次關系圖如下所示:

這裡寫圖片描述

Drawable 的內部寬/高這個參數比較重要,通過 getIntrinsicWidth 和 getIntrinsicHeight 這兩個方法可以獲取到它們。但是並不是所有的 Drawable 都有內部寬/高,比如一張圖片所形成的 Drawable,它的內部寬/高就是圖片的寬/高,但是一個顏色所形成的 Drawable,它就沒有內部寬/高的概念。另外需要注意的是,Drawable 的內部寬/高不等同於它的大小,一般來說,Drawable 是沒有大小概念的,當用作 View 的背景時,Drawable 會被拉伸至 View 的同等大小。

BitmapDrawable

這幾乎是最簡單的 Drawable 了,它表示的就是一張圖片。在實際開發中,我們可以直接引用原始的圖片即可,但是也可以通過 XML 的方式來描述它,通過 XML 來描述的 BitmapDrawable 可以設置更多的效果,如下所示:




下面是它各個屬性的含義:

android:src

這個很簡單,就是圖片的資源 id。

android:antialias

是否開啟圖片抗鋸齒功能。開啟後會讓圖片變得平滑,同時也會在一定程度上降低圖片的清晰度,但是這個降低的幅度較低以至於可以忽略,隱藏抗鋸齒選項應該開啟。

android:dither

是否開啟抖動效果。當圖片的像素配置和手機屏幕的像素配置不一致時,開啟這個選項可以讓高質量的圖片在低質量的屏幕上還能保持較好的顯示效果,比如圖片的色彩模式為 ARGB8888,但是設備屏幕所支持的色彩模式為 RGB5555,這個時候開啟抖動選項可以讓圖片顯示不會過於失真。在 Android 中創建的 Bitmap 一般會選用 ARGB8888 這個模式,即 ARGB 四個通道各占 8 位,在這種色彩模式下,一個像素所占的大小為 4 個字節,一個像素的位數總和越高,圖像也就越逼真。根據分析,抖動效果也應該開啟。

android:filter

是否開啟過濾效果。當圖片尺寸被拉伸或者壓縮時,開啟過濾效果可以保持較好的顯示效果,因此此選項也應該開啟。

android:gravity

當圖片小於容器的尺寸時,設置此選項可以對圖片進行定位。這個屬性的可選項比較多,不同的選項可以通過 “|” 來組合使用,各個屬性的含義如下所示:
top:將圖片放在容器的頂部,不改變圖片的大小。
bottom:將圖片放在容器的底部,不改變圖片的大小。
left:將圖片放在容器的左部,不改變圖片的大小。
right:將圖片放在容器的右部,不改變圖片的大小。
center_vertical:使圖片豎直居中,不改變圖片的大小。
center_horizontal:使圖片水平居中,不改變圖片的大小。
center:使圖片在水平和豎直方向同時居中,不改變圖片的大小。
fill_vertical:使圖片豎直方向填充容器。
fill_horizontal:使圖片水平方向填充容器。
fill:使圖片在水平和豎直方向均填充容器,這是默認值。
clip_vertical:附加選項,表示豎直方向的裁剪,較少使用。
clip_horizontal:附加選項,表示水平方向的裁剪,較少使用。

android:mipMap

這是一種圖像相關的處理技術,也叫紋理映射,比較抽象,這裡也不對其深究了,默認值為 false,在日常開發中此選項不常用。

android:tileMode

平鋪模式。這個選項有如下幾個值:[“disabled” | “clamp” | “repeat” | “mirror”],其中 disable 表示關閉平鋪模式,這也是默認值,當開啟平鋪模式後,gravity 屬性會被忽略。這裡主要說一下 repeat、mirror 和 clamp 的區別,這三者都表示平鋪模式,但是它們的表現卻有很大不同。repeat 表示的是簡單的水平和豎直方向上的平鋪效果;mirror 表示一種在水平和豎直方向上的鏡面投影效果;而 clamp 表示的效果就更加奇特,圖片四周的像素會擴展到周圍區域(常見的是邊緣區域被拉伸)。

接下來說一個和 BitmapDrawable 比較相似的 Drawable —— NinePatchDrawable,它表示的是一張 .9 格式的圖片, .9 圖片可以自動地根據所需的 寬/高 進行相應的縮放並保證不失真,之所以把它和 BitmapDrawable 放在一起介紹是因為它們都表示一張圖片。 和 BitmapDrawable 一樣,在實際使用中直接引用圖片即可,但是也可以通過 XML 來描述 .9 圖,如下所示:


上述 XML 中的屬性的含義 和 BitmapDrawable 中的對應屬性的含義是相同的,這裡就不在描述了,另外,在實際使用中發現在 bitmap 標簽中也可以使用 .9 圖,即 BitmapDrawable 也可以代表一個 .9 格式的圖片;

ShapeDrawable

ShapeDrawable 是一種很常見的 Drawable,可以理解為通過顏色來構造的圖形,它既可以是純色的圖形,也可以是具有漸變效果的圖形。ShapeDrawable 的語法稍顯復雜,如下所示:




    

    

    

    

 

需要注意的是 shape 標簽創建的 Drawable,其實體類實際上是 GradientDrawable,下面分別介紹各個屬性的含義。

android:shape

表示圖形的形狀,有四個選項:rectangle(矩形)、oval(橢圓)、line(橫線) 和 ring(圓環)。它的默認值是矩形,另外 line 和 ring 這兩個選項必須要通過 stroke 標簽來指定線的寬度和顏色等信息,否則將無法達到預期的顯示效果。

針對 ring 這個形狀,有 5 個特殊的屬性:android:innerRadius、android:thickness、android:innerRadiusRatio、android:thicknessRatio 和 android:useLevel,它們的含義如下所示:
android:innerRadiusRatio:內半徑占整個 Drawable 寬度的比例,默認值為 9,如果為 n,那麼內半徑 = 寬度 / n;
android:innerRadius:圓環的內半徑,和 android:innerRadiusRatio 同時存在時,以 android:innerRadius 為准。
android:thicknessRatio:厚度占整個 Drawable 寬度的比例,默認值為 3,如果為 n,那麼厚度 = 寬度 / n;
android:thickness:圓環的厚度,即外半徑 - 內半徑的大小,和 android:thicknessRatio 同時存在時,以 android:thickness 為准。
android:useLevel:一般都應該使用 false,否則有可能無法達到預期的顯示效果,除非它被當作 LevelListDrawable 來使用。

corners

表示 shape 的四個角的角度。它只適用於矩形 shape,這裡的角度是指圓角的程度,用 px 來表示,它有如下 5 個屬性:
- android:radius —— 為四個角同時設定相同的角度,優先級較低,會被其他四個屬性覆蓋。
- android:topLeftRadius —— 設定最左上角的角度;
- android:topRightRadius —— 設定最右上角的角度;
- android:bottomLeftRadius —— 設定最左下角的角度;
- android:bottomRightRadius —— 設定最右下角的角度;

gradient

它與 solid 標簽是互相排斥的,其中 solid 表示純色填充,而 gradient 則表示漸變效果, gradient 有如下幾個屬性:
- android:angle —— 漸變的角度,默認值為 0,其值必須為 45 的倍數,0表示從左到右,90 表示從下到上,具體的效果需要自行體驗,總之角度會影響漸變的方向;
- android:centerX —— 漸變的中心點橫坐標;
- android:centerY —— 漸變的中心點縱坐標,漸變的中心點會影響漸變的具體效果;
- android:startColor —— 漸變的起始色;
- android:centerColor —— 漸變的中間色;
- android:endColor —— 漸變的結束色;
- android:gradientRadius —— 漸變半徑,僅當 android:type=”radial” 時有效;
- android:useLevel —— 一般為 false,當 Drawable 作為 StateListDrawable 使用時為 true;
- android:type —— 漸變的類別,有 linear(線性漸變)、radial(徑向漸變)、sweep(掃描線漸變)三種,其中默認值為線性漸變;
關於效果的展示請大家自行嘗試….

solid

這個標簽表示純色填充,和 gradient 是互相排斥的,通過 android:color 即可指定 shape 中填充的顏色。
- stroke

Shape 的描邊,有如下幾個屬性:
- android:width —— 描邊的寬度,越大則 shape 的邊緣線就會看起來越粗;
- android:color —— 描邊的顏色;
- android:dashWidth —— 組成虛線的線段的寬度;
- android:dashGap —— 組成虛線的線段之間的間隔,間隔越大則虛線看起來空隙就越大。
注意:如果 android:dashWidth 和 android:dashGap 有任何一個為 0,那麼虛線效果將不能生效。

padding

這個表示空白,但是它表示的不是 shape 的空白,而是包含它的 View 的空白,有四個屬性:android:left、android:top、android:right 和 android:bottom。

size

shape 的大小,有兩個屬性:android:width 和 android:height,分別表示 shape 的寬/高。這個表示的是 shape 的固有大小,但是一般來說它並不是 shape 最總顯示的大小,這個有點抽象,但是我們要明白,對於 shape 來說它並沒有 寬/高 的概念,作為 View 的背景它會自適應 View 的 寬/高。我們知道 Drawable 的兩個方法 getIntrinsicWidth 和 getIntrinsicHeight 表示的是 Drawable 的固有 寬/高,對於有些 Drawable 比如圖片來說,它的固有 寬/高 就是圖片的尺寸。而對於 shape 來說,默認情況下它是沒有固有 寬/高 這個概念的,這個時候 getIntrinsicHeight 和 getIntrinsicWidth 就會返回 -1,但是如果我們通過 size 標簽來指定 寬/高 信息,那麼這個時候 shape 就有了所謂的固有 寬/高。因此,總結來說, size 標簽設置的 寬/高 就是 ShapeDrawable 的固有 寬/高,但是作為 View 的背景時,shape 還會被拉伸或者縮小為 View 的大小。。

LayerDrawable

LayerDrawable 對應的 XML 標簽是 layer-list,它表示一種層次化的 Drawable 集合,通過將不同的 Drawable 放置在不同的層上面從而達到一種疊加後的效果。



    

一個 layer-list 中可以包含多個 item,每個 item 表示一個 Drawable。Item 的結構也比較簡單,比較常用額屬性有 android:top、android:bottom、android:left 和 android:right,它們分別表示 Drawable 相對於 View 的上下左右的偏移量,單位為像素。另外,我們可以通過 android:drawable 屬性來直接引用一個已有的 Drawable 資源,也可以在 item 中自定義 Drawable。默認情況下,layer-list 中的所有的 Drawable 都會被縮放至 View 的大小,對於 bitmap 來說,需要使用 android:gravity 屬性才能控制圖片的顯示效果。layer-list 有層次的概念,下面的 item 會覆蓋上面的 item,通過合理的分層,可以實現一些特殊的疊加效果。

StateListDrawable

StateListDrawable 對應於 selector 標簽,它也是表示 Drawable 集合,每個 Drawable 都對應著 View 的一種狀態,這樣系統就會根據 View 的狀態來選擇合適的 Drawable。StateListDrawable 主要用於設置可單擊的 View 的背景,最常見的是 Button,這個大家應該都使用過,它的語法如下所示:




    

針對上面的語法,下面做簡單介紹。

android:constantSize

StateListDrawable 的固有大小是不隨著其狀態的改變而改變的,因為狀態額改變會導致 StateListDrawable 切換到具體的 Drawable,而不同的 Drawable 具有不同的固有大小。 True 表示 StateListDrawable 的固有大小保持不變,這時它的固有大小是內部所有 Drawable 的固有大小的最大值,false 則會隨著狀態的改變而改變。此選項默認值為 false。

android:dither

是否開啟抖動效果,這個在 BitmapDrawable 中也有提到,開啟此選項可以讓圖片在低質量的屏幕上仍然獲得較好的顯示效果。此選項默認值為 true。

android:variablePadding

StateListDrawable 的 padding 表示是否隨著其狀態的改變而改變,true 表示會隨著狀態的改變而改變,false 表示 StateListDrawable 的 padding 是內部所有 Drawable 的 padding 的最大值。此選項默認值為 false,並且不建議開啟此選項。

item 標簽

item 標簽表示一個具體的 Drawable,它的結構也比較簡單,其中 android:drawable 是一個已有 Drawable 的資源 id,剩下的屬性表示的是 View 的各種狀態,每個 item 表示的都是一種狀態下的 Drawable 信息。View 的常見狀態如下表:
- android:state_pressed —— 表示按下狀態,比如 Button 被按下後仍然沒有松開時的狀態
- android:state_focused —— 表示 View 已經獲取了焦點;
- android:state_selected —— 表示用戶選擇了 View;
- android:state_checked —— 表示用戶選中了 View,一般適用於 CheckBox 這類在選中 和 非選中狀態之間進行切換的 View;
- android:state_enabled —— 表示 View 當前處於可用狀態。

下面給出具體的例子,代碼如下所示:



    
    
    
    
    
    

系統會根據 View 當前的狀態從 selector 中選擇對應的 item,每個 item 對應著一個具體的 Drawable,系統按照從上到下的順序查找,直至查找到第一條匹配的 item。一般來說,默認的 item 都應該放在 selector 的最後一條並且不附帶任何的狀態,這樣上面的 item 都無法匹配 View 的當前狀態,系統就會選擇默認的 item,因為默認的 item 不附帶狀態,所以它可以匹配 View 的任何狀態。

LevelListDrawable

LevelListDrawable 對應於 level-list 標簽,它同樣表示一個 Drawable 集合,集合中的每個 Drawable 都有一個等級 (level)的概念。根據不同的等級,LevelListDrawable 會切換為對應的 Drawable,它的語法如下所示:



    

上面的語法中,每個 item 表示一個 Drawable,並且有對應的等級范圍,由 android:minLevel 和 android:maxLevel 來指定,在最小值和最大值之間的等級會對應此 item 中的 Drawable。下面是一個實際的例子,當它作為 View 的背景時,可以通過 Drawable 的 setLevel 方法來設置不同的等級從而切換具體的 Drawable。如果它被用來作為 ImageView的前景 Drawable,那麼還可以通過 ImageView 的 setImageLevel 方法來切換 Drawable。最後,Drawable 的等級是有范圍的,即 0~10000,最小等級是 0 ,這也是默認值,最大等級是 10000.



    

    

TransitionDrawable

TransitionDrawable 對應於 transition 標簽,它用於實現兩個 Drawable 之間的淡入淡出效果,它的語法如下所示。



    

上面語法中的屬性前面已經都介紹過了,其中 android:top、android:right、android:bottom 和 android:left仍然表示的是 Drawable 四周的偏移量,這裡就不多介紹了。下面給出一個實際的例子。

首先定義 TransitionDrawable,如下所示。



    
    


最後,通過它的 startTransition 和 reverseTransition 方法來實現淡入淡出的效果以及它的逆過程,如下所示:

TextView textView = (textView) findViewById(R.id.button);
TransitionDrawable drawable = (TransitionDrawable) textView.getBackground();
drawablel.startTransition(1000);

InsetDrawable

InsetDrawable 對應於 inset 標簽,它可以將其他 Drawable 內嵌到自己當中,並可以在四周留出一定的間距。當一個 View 希望自己的背景比自己的實際區域小的時候,可以采用 InsetDrawable 來實現,同時我們知道,通過 LayoutDrawable 也可以實現這種效果。InsetDrawable 的語法如下所示:


上面的屬性都比較好理解,其中 android:insetTop、android:insetRight、android:insetLeft 和 android:insetBottom 分別表示頂部、右邊、左邊 和 底部 內凹的大小。在下面的例子中,inset 中的 shape 距離 View 的邊界為 15dp。




    
        
    

ScaleDrawable

ScaleDrawable 對應於 scale 標簽,它可以根據自己的等級(level)將指定的 Drawable 縮放到一定比例,它的語法如下所示:


從上面的屬性中,android:gravity 的含義等同於 shape 中的 android:gravity,而 android:scaleWidth 和 android:scaleHeight 分別表示對指定 Drawable 寬 和 高 的縮放比例,以百分比的形式表示,比如 25%。

ScaleDrawable 的作用更偏向於 縮小一個特定的 Drawable。從下面的例子中,可以近似地將一張圖片縮小為原大小的 30%,代碼如下所示:


直接使用上面的 drawable 資源是不行的,還必須設置 ScaleDrawable 的等級為大於 0 且小於等於 10000 的值,如下所示:

View testScale = findViewById(R.id.test_scale);
ScaleDrawable testScaleDrawable = (ScaleDrawable) testScale.getBackground();
testScaleDrawable.setLevel(1);

ClipDrawable

ClipDrawable 對應於 clip 標簽,它可以根據自己當前的等級 (level) 來裁剪另一個 Drawable,裁剪方向可以通過 android:clipOrientation 和 android:gravity 這兩個屬性來共同控制,它的語法如下所示:


其中 clipOrientation 表示裁剪方向,有水平和豎直兩個方向,gravity 比較復雜,需要 和 clipOrientation 一起才能發揮作用。另外 gravity 的各種選項是可以通過 “|”來組合使用的。

gravity 的各個屬性介紹如下:

top:將內部的Drawable 放在容器的頂部,不改變它的大小,如果為豎直裁剪,那麼從底部開始裁剪。 bottom:將內部的Drawable 放在容器的底部,不改變它的大小,如果為豎直裁剪,那麼從頂部開始裁剪。 left:將內部的Drawable 放在容器的左邊,不改變它的大小,如果為水平裁剪,那麼從右邊開始裁剪,這是默認值。 right:將內部的Drawable 放在容器的右邊,不改變它的大小,如果為水平裁剪,那麼從左邊開始裁剪。 center_vertical:將內部的Drawable 在容器中豎直居中,不改變它的大小,如果為豎直裁剪,那麼從上下同時開始裁剪。 center_horizontal:將內部的Drawable 在容器中水平居中,不改變它的大小,如果為水平裁剪,那麼從左右兩邊同時開始裁剪。 fill_vertical:使內部的 Drawable 在豎直方向上填充容器,如果為豎直裁剪,那麼僅當 ClipDrawable 的等級為 0 (0表示 ClipDrawable 被完全裁剪,即不可見)時,才能有裁剪行為。 fill_horizontal:使內部的 Drawable 在水平方向上填充容器,如果為水平裁剪,那麼僅當 ClipDrawable 的等級為 0 時,才能有裁剪行為。 center:使內部 Drawable 在容器中水平和豎直方向都居中,不改變它的大小,如果為豎直裁剪,那麼從上下同時開始裁剪;如果為水平裁剪,那麼從左右同時開始裁剪。 fill:使內部的 Drawable 在水平和豎直方向上同時填充容器。僅當 ClipDrawable 的等級為 0 時,才能有裁剪行為 clip_vertical:附加選項,表示豎直方向的裁剪,較少使用。 clip_horizontal:附加選項,表示水平方向的裁剪,較少使用。

下面我們舉個例子,我們實現將一張圖片從上往下進行裁剪的效果,首先定義 ClipDrawable,XML如下:



``
在上面的 XML 中,因為我們要實現頂部的裁剪效果,所以裁剪方向應該為 豎直方向,同時從上面的屬性介紹中可以知道,gravity 屬性應該選擇 bottom。有了 ClipDrawable 如何使用呢? 也很簡單的,首先將它設置給 我們的 View,如下所示:

 

接著在代碼中設置 ClipDrawable 的等級,如下所示:

ImageView testClip = (ImageView) findViewById(R.id.test_clip);
ClipDrawable testClipDrawable = (ClipDrawable) testClip.getDrawable();
testClipDrawable.setLevel(8000);
“`
在上面已經提到,Drawable 的等級 (level)是有范圍的,即 0-10000,最小等級是 0,最大等級是 10000,對於 ClipDrawable 來說,等級 0 表示完全裁剪,即整個 Drawable 都不可見了,而等級 10000 表示不裁剪。將上面的代碼中的等級設置為 8000 表示裁剪了2000,即在頂部裁剪掉 20% 的區域,被裁剪的區域就相當於不存在了。

對於本例來說,等級越大,表示裁剪的區域越小,因此等級 10000 表示不裁剪,這個時候這個圖片都可以完全顯示出來;而等級 0 則表示裁剪全部區域,這個時候整個圖片將不可見。另外裁剪效果還受裁剪方向和 gravity 屬性的影響,大家可自行嘗試,這樣就能比較好地理解不同屬性對裁剪效果的影響了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved