Android開發中,和布局文件對應 View 一樣,Drawable 文件也對應著一個類--Drawable。
如下面兩個表所示。
節點 | View 類 | 類型 |
---|---|---|
LinearLayout | android.widget.LinearLayout | ViewGroup |
TextView | android.widget.TextView | View |
Button | android.widget.Button | View |
... | ... | ... |
假設在布局文件的根布局使用了 LinearLayout , 里面包含了一個 TextView 和 一個 Button,隨后在 Activity 中使用 setContentView(R.layout.main);
或者使用 LayoutInflater.from(mContext).inflate(R.id.main, null, false);
來加載 view,Android 會把布局文件中的每個節點都轉換對應的類,組合成一個新的 view,用在 Activity 背景上或者得到這個 view做其他的操作。
下面來看今天的主題---Drawable,以布局文件來類比。
序號 | 節點 | Drawable 具體子類 | 說明 |
---|---|---|---|
1 | [bitmap] | BitmapDrawable | 對bitmap的封裝 |
2 | [color] | ColorDrawable | 把顏色封裝成可以顯示的Drawable |
3 | [shape] | ShapeDrawable | 繪制基礎的形狀圖形,最常用的Drawable之一,可用于定義圓角、漸變色、圓環等效果 |
4 | [selector] | StateListDrawable | 表示一組有狀態的圖像的集合,可用于給button等設置點擊和正常狀態下的圖片 |
5 | [level-list] | LevelListDrawable | 表示一組有等級的圖像的集合 |
6 | [layer-list] | LayerDrawable | 表示圖層 |
7 | [nine-patch] | NinePatchDrawable | 對.9.png的封裝 |
8 | [clip] | ClipDrawable | 對drawable裁剪 |
9 | [inset] | InsetDrawable | 用距離邊框的距離表示drawable大小 |
10 | [ripple] | RippleDrawable | 波紋點擊效果,API21以上 |
下面看怎樣在xml文件中使用這些 Drawable,當然和布局文件中的 view 一樣,我們也可以使用java代碼來創建這些對象,但是我們一般不這樣做,就像我們不會用java代碼創建一個復雜的布局一樣。
一、BitmapDrawable
在 drawable 文件夾下創建一個xml文件,修改 <selector/>
根節點為 <bitmap/>
,并且增加 src 屬性,像下面這樣:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_launcher">
</bitmap>
這樣,我們就可以在文件文件中設置 view 的背景 android:background="@drawable/bitmap"
,bitmap 就這么簡單,我們一般也不會這樣來用,使用的話也是配合別的 Drawable,用于包裝圖片資源,比如在 StateListDrawable(selector節點)下,對應每一個drawable 設置不同的 BitmapDrawable。
bitmap 節點下不能再包含節點。
所有的設置都通過屬性來完成。
下表列出所有的屬性供參考。
屬性 | 參數類型 | 說明 |
---|---|---|
android:src | Drawable resource | 顯示的圖片,不能為color等,只能為圖片資源 |
android:alpha | float | 透明度0-1,值越小,越透明 |
android:antialias | boolean | 是否開啟抗鋸齒 |
android:autoMirrored | boolean | 設置圖片是否需要鏡像反轉,當布局方向是RTL,即從右到左布局時才有用,API19以上 |
android:dither | boolean | 是否抖動 |
android:filter | boolean | 設置是否允許對圖片進行濾波 |
android:gravity | center... | 圖片對其方式,同布局文件中view的gravity屬性 |
android:mipMap | boolean | 設置是否可以使用mipmap API18以上 |
android:tileMode | disabled、mirror、clamp、repeat | X、Y軸平鋪方式, disabled(默認):不使用平鋪;mirror:鏡面;clamp:復制圖片邊緣的顏色來填充容器剩下的空白部分;repeat:圖片重復鋪滿 |
android:tileModeX | 同上 | X軸平鋪方式,參數意義同上 |
android:tileModeY | 同上 | Y軸平鋪方式,參數意義同上 |
android:tint | color | 給圖片著色 |
android:tintMode | add、multiply、screen、src_atop、src_in、src_over | 著色模式 |
二、ColorDrawable
ColorDrawable 對應xml文件中的 <color/>
節點,同樣在 drawable 文件夾下新建一個xml文件,內容如下:
<?xml version="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/colorAccent">
</color>
color 節點只有唯一一個也是必須的屬性,android:color
使用color資源文件中的color賦值即可。同樣沒有子節點,最為簡單的一個Drawable,把color 值轉化為了Drawable對象,以便在其他需要Drawable的地方使用。
三、ShapeDrawable
使用 <shape/>
節點用來定義形狀,可以定義矩形、橢圓、線、圓環四種類型的形狀。shape 節點包含一些屬性和子節點:
屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:shape | rectangle、oval、line、ring | 定義形狀的類型,rectangle(矩形)、oval(橢圓)、line(線)、ring(圓環)默認為矩形 |
android:innerRadius | int | 圓環內圓的半徑 |
android:innerRadiusRatio | int | 內半徑占整個Drawable寬度的比例,默認值為9 |
android:thickness | int | 圓環的厚度 |
android:thicknessRatio | int | 厚度占整個Drawable寬度比例,默認值為3 |
android:useLevel | boolean | 設置等級,配合LevelListDrawable使用時設置 |
android:visible | boolean | 設置是否可見 |
android:dither | boolean | 是否抖動 |
android:tint | color | 給圖片著色 |
android:tintMode | add、multiply、screen、src_atop、src_in、src_over | 著色模式 |
子節點:
solid 填充色
表示形狀的填充色,只有color一個屬性:android:color
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorAccent"/>
</shape>
填充顏色的矩形.png
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/colorAccent"/>
</shape>
填充顏色的橢圓.png
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="50dp"
android:shape="ring"
android:thickness="10dp"
android:useLevel="false">
<solid android:color="@color/colorAccent"/>
</shape>
填充顏色的圓環.png
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:width="4dp"
android:color="@color/colorAccent"
android:dashGap="8dp"
android:dashWidth="4dp"/>
</shape>
線.png
corners 圓角
表示圓角的半徑,對應有四個角的屬性,和一個總體的屬性
屬性 | 參數類型 | 說明 |
---|---|---|
android:radius | int | 統一設置圓角半徑 |
android:bottomLeftRadius | int | 設置左下角圓角半徑 |
android:bottomRightRadius | int | 設置右下角圓角半徑 |
android:topLeftRadius | int | 設置左上角圓角半徑 |
android:topRightRadius | int | 設置右上角圓角半徑 |
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:bottomLeftRadius="3dp"
android:radius="5dp"/>
<solid android:color="@color/colorAccent"/>
<size
android:width="30dp"
android:height="30dp"/>
</shape>
圓角.png
gradient 漸變色
表示漸變色,可以設置形狀填充的顏色為漸變色
屬性 | 參數類型 | 說明 |
---|---|---|
android:angle | int | 設置旋轉的角度,45的倍數 |
android:startColor | color | 顏色變化的起始值 |
android:endColor | color | 顏色變化的結束值 |
android:centerColor | color | 中間的顏色 |
android:centerX | int | 漸變中心點的橫坐標 |
android:centerY | int | 漸變的中心點的縱坐標 |
android:gradientRadius | int | 漸變的梯度,當android:type=”radial”有效 |
android:type | linear 、 radial 、 sweep | 漸變類別,linear(線性)為默認值,radial(徑內漸變),sweep(掃描漸變) |
android:useLevel | boolean | 設置等級,配合LevelListDrawable使用時設置 |
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:type="sweep"
android:endColor="@color/colorAccent"
android:startColor="@color/colorPrimary"/>
<size
android:width="30dp"
android:height="30dp"/>
</shape>
漸變色.png
stroke 邊框
表示邊框。
屬性 | 參數類型 | 說明 |
---|---|---|
android:color | color | 邊框顏色 |
android:width | int | 邊框寬度 |
android:dashGap | int | 邊框虛線間隙大小 |
android:dashWidth | int | 邊框虛線每個小節的寬度 |
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="2dp"
android:color="@color/colorAccent"
android:dashGap="2dp" // 和dashWidth一起設置,若不設置則為實線
android:dashWidth="3dp"/>
<size
android:width="30dp"
android:height="30dp"/>
</shape>
虛線邊框.png
size 大小
設置背景大小,width和height倆屬性。一般來說這個值不是shape的最終顯示大小,因為shape作為背景時會根據View的大小而填充其背景,因此Shape的大小很多時候是View的大小決定的。
padding 內邊距
表示內容或子標簽邊距,4個屬性top、bottom、left、right,需要注意的是這個標簽的作用是為內容設置與當前應用此shape的View的邊距,而不是設置當前View與父元素的邊距。
四、StateListDrawable
StateListDrawable 對應 drawable 文件夾下的xml文件的 <selector/>
節點,表示drawable集合。selector 可以包含不止一個 item 節點,每個 item 節點對應兩類屬性,一類只有一個 android:drawable
, 另一類是類似于 android:state_pressed
,表示當前所在view的狀態,有按下、選擇、獲得焦點等十幾種狀態,需要注意不是每一個view都有這么多狀態。
最常見的場景是給 Button 設置點擊和正常狀態下的drawable。
selector 節點 屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:autoMirrored | boolean | 設置圖片是否需要鏡像反轉 |
android:constantSize | boolean | 設置自身大小是否隨著其狀態改變而改變 |
android:enterFadeDuration | int | 狀態改變時,新狀態展示時的淡入時間,以毫秒為單位 |
android:exitFadeDuration | int | 狀態改變時,新狀態消失時的淡入時間,以毫秒為單位 |
android:variablePadding | boolean | padding是否隨狀態的改變而改變,默認false |
子節點 item 屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:drawable | drawable | 對應drawable,可以為color、bitmap、shape等單一drawable |
android:android:state_xxx | boolean | 設置不同的狀態 |
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/button_press"
android:state_pressed="true"/>
<item android:drawable="@color/button_norm"
android:state_pressed="false"/>
</selector>
子節點 item 還可以包含許多子節點,如bitmap、shape、color、動畫相關的等,下面給出兩個例子說明用法。
在布局文件中給view設置 android:background="@drawable/button_seleter"
即可,實現在點擊view時顯示不同的背景圖,有點擊的效果反饋。
這里需要注意一點:
如果上邊所說的view是 Button 的話,直接可以看到效果,但是,實際開發中,我們可能要給 LinearLayout、TextView 設置點擊效果,使用上面的方法是沒有效果的。
解決方法:給這個 view 添加點擊事件的監聽。
上邊代碼中的 android:drawable
不只可以設置為color類型的drawable,還可以設置為bitmapDarwable、ShapeDrawable等,下面看一個圓角點擊效果的例子。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape>
<corners android:radius="10dp"/>
<solid android:color="@color/button_norm"/>
</shape>
</item>
<item android:state_pressed="true">
<shape>
<corners android:radius="10dp"/>
<solid android:color="@color/button_press"/>
</shape>
</item>
</selector>
設置在view上的效果為有圓角效果,并且按下的時候,背景后改變。
以上代碼在 selector 節點下有兩個 item 節點,item節點設置了是否點擊的狀態,并且包含了一個 shape 節點,作為對應狀態下的drawable對象。
五、LevelListDrawable
LevelListDrawable 對應xml文件中的 <level-list/>
節點,表示一組由等級大小標志的 drawable,不同的等級可以為之設置不同的背景drawable。
此節點沒有參數,只能包含不止一個的 item 子節點。
item 節點的屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:drawable | drawable | 對應drawable,可以為color、bitmap、shape等單一drawable |
android:maxLevel | int | 設置等級范圍的最大值 |
android:minLevel | int | 設置等級范圍的最小值 |
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/colorAccent"
android:maxLevel="10"
android:minLevel="1"/>
<item
android:drawable="@color/colorPrimary"
android:maxLevel="20"
android:minLevel="11"/>
</level-list>
簡單起見,使用 ColorDrawable 來設置對應的 android:drawable,有兩種不同的背景,對應都有不同的等級范圍。
設置給view 作為背景,像這樣:android:background="@drawable/level"
。
在java代碼中,獲取到此view的 background,再設置其level屬性的值,就會變為對應等級的背景。
boolean flag;
public void onClick(View v) {
if (flag) {
view.getBackground().setLevel(3);
} else {
view.getBackground().setLevel(13);
}
this.flag = !this.flag;
}
六、LayerDrawable
LayerDrawable 也表示 drawable 集合,對應xml文件中的<layer-list/>
節點,根據名稱我們可以知道其中的每一個 drawable 都代表一個圖層,新加入的 drawable 位于背景圖片的最高圖層。
item 的 android:drawable 屬性也是可以設置為復雜的drawable的,方便起見,這里使用 colorDrawable。
屬性 | 參數類型 | 說明 |
---|---|---|
android:opacity | transparent、translucent、opaque | 設置透明度:transparent透明、translucent半透明、opaque不透明 |
android:paddingXxx | int | 設置等級范圍的最大值 |
子節點 item 屬性,都是定位的屬性,像height,width,gravity,bottom,top,left,right等。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="10dp"
android:drawable="@color/colorAccent"
android:left="10dp"
android:right="10dp"
android:top="10dp"
/>
<item
android:bottom="50dp"
android:drawable="@color/colorPrimary"
android:left="50dp"
android:right="50dp"
android:top="50dp"
/>
</layer-list>
效果如下:
七、NinePatchDrawable
NinePatchDrawable 是點九圖的封裝,xml文件中對應 <nine-patch/>
標簽,屬性和BitmapDrawable中屬性的含義相同。
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/btn_bk"
android:dither="true"/>
八、ClipDrawable
ClipDrawable 代表可以裁剪的drawable,對應xml文件中的<clip/>
標簽,通過當前設置的比例來裁剪Drawable,ClipDrawable的setLevel()方法可以控制顯示比例,ClipDrawable的level值范圍在[0,10000],level的值越大裁剪的內容越少,當level為10000時則完全顯示,而0表示完全裁剪,不可見。
<clip/>
標簽的屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:drawable | drawable | 對應drawable,可以為color、bitmap、shape等單一drawable |
android:clipOrientation | horizontal、vertical | 裁剪的方向,horizontal水平、vertical垂直 |
android:gravity | right、top等 | 設置drawable所在位置,配合android:clipOrientation 屬性一起用 |
android:gravity 可以設置下表所示的值:
屬性 | 描述說明 |
---|---|
top | 將這個對象放在容器的頂部,不改變其大小。當clipOrientation 是”vertical”,裁剪從底部開始 |
bottom | 將這個對象放在容器的底部,不改變其大小。當clipOrientation 是”vertical”,裁剪從頂部開始 |
left | 將這個對象放在容器的左部,不改變其大小。當clipOrientation 是 “horizontal”,裁剪從drawable的右邊(right)開始,默認值 |
right | 將這個對象放在容器的右部,不改變其大小。當clipOrientation 是 “horizontal”,裁剪從drawable的左邊(left)開始 |
center | 將這個對象放在水平垂直坐標的中間,不改變其大小。當clipOrientation 是 “horizontal”裁剪發生在左右。當clipOrientation是”vertical”,裁剪發生在上下。 |
center_vertical | 將對象放在垂直中間,不改變其大小,如果clipOrientation 是 “vertical”,那么從上下同時開始裁剪 |
center_horizontal | 將對象放在水平中間,不改變其大小,clipOrientation 是 “horizontal”,那么從左右兩邊開始裁剪 |
fill | 填充整個容器,不會發生裁剪。(除非drawable的level是 0,才會不可見,表示全部裁剪完)。 |
fill_vertical | 垂直方向上不發生裁剪。(除非drawable的level是 0,才會不可見,表示全部裁剪完) |
fill_horizontal | 水平方向上不發生裁剪。(除非drawable的level是 0,才會不可見,表示全部裁剪完) |
clip_vertical | 附加選項,表示豎直方向的裁剪,很少使用 |
clip_horizontal | 附加選項,表示水平方向的裁剪,很少使用 |
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal"
android:drawable="@drawable/ic_launcher"
android:gravity="right">
</clip>
上邊代碼定義了一個 ClipDrawable 對象,設置進行水平方向裁剪,并且從左邊開始裁剪。drawable為app啟動圖標。
在布局文件的view中使用像 android:background="@drawable/clip"
代碼來使用上邊定義的 ClipDrawable。
在java代碼中,通過設置 ClipDrawble 的 level 屬性的值,來進行圖片背景的裁剪。
linearLayout = (LinearLayout) findViewById(R.id.lll);
linearLayout.getBackground().setLevel(5000); // 裁剪一半,0~10000
效果如下圖:
九、InsetDrawable
InsetDrawable 用距離邊框的距離表示drawable大小,比如我們需要讓view的背景不是完全填充這個view,并且需要一定的距離,就可以使用 InsetDrawable 來完成。InsetDrawable 對應xml文件中的 <inset/>
標簽。
屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:drawable | drawable | 對應drawable,可以為color、bitmap、shape等單一drawable |
android:inset | dimen | 統一設置距離邊框的距離 |
android:insetTop | dimen | 設置距容器上邊的距離 |
android:insetBottom | dimen | 設置距容器下邊的距離 |
android:insetLeft | dimen | 設置距容器左邊的距離 |
android:insetRight | dimen | 設置距容器右邊的距離 |
android:visible | boolean | 設置是否可見 |
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@color/colorAccent"
android:inset="10dp">
</inset>
十、RippleDrawable
RippleDrawable 可以在Android5.0 即 API21 以上實現波紋點擊效果,對應xml文件中的 <ripple/>
標簽。由于此標簽必須在API21以上才可以使用,我們也不能設置 minSdkVersion
為21,畢竟要適配更多的API版本,我們可以在建立一個 drawable-v21
的文件夾,在里面新建一個xml文件即可。
在Android studio中,就更方便了,選中 Drawable 文件夾--->右鍵--->選擇new--->單擊 Drawable resource file 選項,就來到了如下對話框:
填寫文件名,選擇最后一個Version,單擊中間的表示向右的按鈕,填寫21,點擊ok,就會自動生成對應文件和新建文件。
<ripple/>
標簽的屬性:
屬性 | 參數類型 | 說明 |
---|---|---|
android:color | color | 波紋的顏色,會覆蓋在背景上 |
android:radius | dimen | 圓角,不太懂,設置大小效果都一樣 |
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/gray">
<!--有界-->
<item
android:id="@android:id/mask"
android:drawable="@color/gray"/>
</ripple>
需要注意的是 android:id="@android:id/mask"
,沒有設置時,是無邊界的波紋效果,添加后為有邊界。
參考博文:
參考視頻教程: