Drawable每天用,可你是否對Drawable家族有一個完整的認知?今天咱們就來系統的學習一下Drawable的使用。java
1.概述
用過Drawable的筒子都知道Drawable有不少種,有的時候Drawable是一張圖片,有的時候Drawable是咱們經過顏色構造出來的某種圖形。最多見的本身構造的Drawable圖形莫過於ShapeDrawable,咱們在開發中可能常常須要本身繪製一個矩形、圓形、橢圓等等各類各樣的圖形。通常來講,Drawable並沒大小的概念(雖然能夠經過getIntrinsicHeight和getIntrinsicWidth兩個方法獲取Drawable的寬和高,可是這兩個方法並不老是有效,由於若是咱們的Drawable是圖片的話,那麼Drawable的大小就是圖片的大小,若是咱們的Drawable自己就是顏色的話,那麼就沒有寬高的概念),由於咱們在用Drawable的時候,大多數時候都是把它看成某一個控件的背景來使用的,此時Drawable會被拉伸到和View相同的大小,此時Drawable的大小實際上就是控件的大小。接下來咱們來看看Drawable的繼承關係:android

在Drawable的這些繼承類中咱們經常使用的主要有如下幾種:LayerDrawable、ShapeDrawable、NinePatchDrawable、BitmapDrawable、StateListDrawable、LevelListDrawable、TransitionDrawable、InsetDrawable、ScaleDrawable、ClipDrawable等,下面咱們會就這些不一樣的Drawable一一介紹。學習
2.BitmapDrawable
BitmapDrawable算是最最最最多見的Drawable之一,咱們構造一個Bitmap對象的時候,有時候會用到BitmapDrawable,那麼BitmapDrawable的構造,除了在代碼中new一個BitmaDrawable以外,咱們還可使用XML來構造一個BitmapDrawable對象,在項目的drawable文件中新建立一個xml文件,代碼以下:spa
- <?xml version="1.0" encoding="utf-8"?>
- <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:antialias="true"
- android:src="@drawable/a2w"
- android:dither="true"
- android:filter="true"
- android:gravity="top|left"
- android:tileMode="mirror"
- >
- </bitmap>
這裏只有src屬性是必須的,該屬性指這個BitmapDrawable要顯示的圖片,其餘屬性看單詞意思都很容易明白,antialias表示是否開啓抗鋸齒,這個在自定義View建立Paint時常常用到;dither表示是否開啓抖動效果,做用是手機像素配置和圖片像素配置不一致時,系統會自動調整顯示效果,關於圖片像素問題參見Android開發之Bitmap二次採樣文章;filter表示是否開啓過濾效果,這個屬性也是爲了使圖片被放大或者縮小時有一個較好的顯示效果;gravity屬性則表示當圖片的大小小於控件的大小時,圖片的顯示位置,tileMode表示平鋪模式,在咱們的Windows電腦桌面設置的時候就有這個選項,該屬性共有四種取值,分別是disable、repeat、mirror、clamp四種,默認狀況下是disable,就是不作任何處理,當咱們在這裏使用了除disable以外的另外三種取值時,gravity屬性值失效。下面咱們來看看這三種取值時的效果:.net
個人原圖是這樣的:3d

個人bitmapdrawable是這樣的:xml
- <?xml version="1.0" encoding="utf-8"?>
- <bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:antialias="true"
- android:src="@drawable/p2"
- android:dither="true"
- android:filter="true"
- android:gravity="top|left"
- android:tileMode="repeat"
- >
- </bitmap>
個人View是這樣的:對象
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="org.mobiletrain.drawable.MainActivity">
-
- <View
- android:layout_width="400dp"
- android:layout_height="400dp"
- android:background="@drawable/mybitmap"/>
- </RelativeLayout>
這是顯示效果是這樣的:blog

你們看到,當圖片的大小小於控件的大小時,圖片會在水平方向和垂直方向不斷的重複。若是我把tileMode屬性的值改成clamp,咱們再來看看顯示效果:繼承

你們看到,這時當圖片小於控件的大小時,圖片在水平方向或者垂直方向末端的顏色會自動延伸直至將控件填充滿。最後咱們再來看看mirror屬性,爲了方便看到效果,我這裏把圖片換一下,咱們再來看看顯示效果:

你們看到一個小飛機在水平方向和垂直方向以倒影的形式在不斷的重複。這就是mirror的顯示效果。
3.ShapeDrawable
shapeDrawable又是一個很是經常使用的Drawable,咱們在開發中對於純色的背景通常來講都是繪製的,由於直接使用圖片會使App打包後變得比較大,經過XML來繪製純色背景是一個不錯的選擇。關於這個我這裏就再也不多說了,你們查看這篇文章自行了解。android開發之shape詳解。
4.LayerDrawable
LayerDrawable表示一個層次化的Drawable,這個要怎麼理解呢?你們看看我以前的這篇文章就理解了博客關於ProgressBar的美化問題。
LayerDrawable中能夠有n多個item,每一個item就是一個Drawable,每個Drawable依據代碼的順序相互覆蓋着顯示出來。先寫的先繪製,後寫的後繪製,最終顯示的效果是一個疊加的顯示效果,咱們來看下面一個例子:
- <?xml version="1.0" encoding="utf-8"?>
- <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item>
- <shape android:shape="rectangle">
- <solid android:color="@color/lineColor"/>
- </shape>
- </item>
- <item android:bottom="8dp">
- <shape android:shape="rectangle">
- <solid android:color="@color/lineColor2"/>
- </shape>
- </item>
- <item android:bottom="1dp" android:left="1dp" android:right="1dp">
- <shape android:shape="rectangle">
- <solid android:color="@color/etbg"/>
- </shape>
- </item>
- </layer-list>
我把這個Drawable做爲EditText的背景,代碼以下:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- android:orientation="vertical"
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="8dp"
- tools:context="org.mobiletrain.drawable.MainActivity">
- <EditText
- android:background="@drawable/textview_background"
- android:layout_width="match_parent"
- android:text="江南一點雨"
- android:layout_height="wrap_content"/>
- <EditText
- android:text="江南一點雨"
- android:layout_marginTop="20dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
顯示效果以下(上面是加了背景的顯示效果,下面是正常的EditText的顯示效果):

你們看到,上面的EditText有一點不一樣,緣由在於我在LayerDrawable中首先繪製了一個藍色的矩形,而後又繪製了一個綠色的矩形,可是這個綠色矩形距離底部有8dp的高度,這就保證了輸入框有兩個向上翹起的藍色邊框,最後繪製整個背景色,整個背景色爲黃色,可是背景色距離左右下三邊的距離分別爲1dp,這樣就確保了另外三條線能夠正常顯示出來。OK,就是這麼簡單,更酷炫的用法參見關於ProgressBar的美化問題。
5.LevelListDrawable
LevelListDrawable,顧名思義就是一個等級Drawable,它就是根據控件的不一樣等級來切換Drawable,有點相似於selector中的根據控件的狀態來更新Drawable。不一樣的是這裏是根據控件的level來更新。好比下面一個簡單的LevelListDrawable文件:
- <?xml version="1.0" encoding="utf-8"?>
- <level-list xmlns:android="http://schemas.android.com/apk/res/android">
- <item
- android:drawable="@drawable/p2"
- android:maxLevel="10"
- android:minLevel="0"/>
- <item
- android:drawable="@drawable/p1"
- android:minLevel="11"
- android:maxLevel="20"/>
- </level-list>
這個levelListDrawable文件表示當控件的level處於0~10之間的時候,顯示圖片p2,當控件的level處於11~20之間的時候顯示圖片p1,咱們來看看個人ImageView:
- <ImageView
- android:layout_width="200dp"
- android:scaleType="centerCrop"
- android:id="@+id/iv"
- android:src="@drawable/level_list_drawable"
- android:layout_height="200dp"/>
在ImageView中將剛纔的LevelListDrawable對象做爲它的src,而後當我點擊按鈕的時候改變ImageView的level,這個時候圖片就會發生變化。點擊事件代碼以下:
- public void toggle(View view) {
- if (flag) {
- iv.setImageLevel(5);
- flag = false;
- }else{
- iv.setImageLevel(15);
- flag = true;
- }
- }
顯示效果以下:

這裏你們須要注意的是level的取值範圍爲0~10000,默認值爲0。
6.TransitonDrawable
TransitionDrawable主要是實現兩個Drawable之間淡入淡出的效果。咱們來看看TransitionDrawable文件:
- <?xml version="1.0" encoding="utf-8"?>
- <transition xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/p1"/>
- <item android:drawable="@drawable/p2"/>
- </transition>
再來看看ImageView文件:
- <ImageView
- android:layout_width="200dp"
- android:scaleType="centerCrop"
- android:id="@+id/iv"
- android:src="@drawable/transition_drawable"
- android:layout_height="200dp"/>
點擊事件以下:
- public void toggle(View view) {
- TransitionDrawable drawable = (TransitionDrawable) iv.getDrawable();
- drawable.startTransition(2000);
- }
顯示效果以下 :

7.InsetDrawable
InsetDrawable表示能夠將一個Drawable嵌入到本身當中。相似的效果使用LayerDrawable也能實現。來看看代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetBottom="20dp"
- android:insetLeft="20dp"
- android:insetRight="20dp"
- android:insetTop="20dp">
- <shape android:shape="oval">
- <solid android:color="@color/colorAccent"/>
- </shape>
- </inset>
表示中心的圓形與控件的上下左右四邊的間距都爲20dp,固然這個設置圖像的地方也能夠像下面這種方式來寫:
- <?xml version="1.0" encoding="utf-8"?>
- <inset xmlns:android="http://schemas.android.com/apk/res/android"
- android:insetBottom="20dp"
- android:drawable="@drawable/p1"
- android:insetLeft="20dp"
- android:insetRight="20dp"
- android:insetTop="20dp">
- </inset>
8.ClipDrawable
表示根據一個Drawable的level對Drawable進行剪裁,代碼以下:
- <?xml version="1.0" encoding="utf-8"?>
- <clip
- android:drawable="@drawable/p1"
- android:clipOrientation="horizontal"
- android:gravity="left"
- xmlns:android="http://schemas.android.com/apk/res/android">
- </clip>
drawable表示drawable圖像,clipOrientation表示剪裁的方向,是從水平方向剪裁仍是從垂直方向剪裁,這個屬性配合gravity屬性纔會生效,至於每次剪裁的百分比則是和level屬性的值有關,level屬性的取值範圍爲0~10000,0表示徹底剪裁,10000表示徹底不剪裁,5000則表示剪裁通常,其它值依此類推。