Android中Drawable知識總結

本文是學習《Android開發藝術探索》中Drawable章節以後的一個總結。android

1、常見的Drawable種類介紹

Drawable類 xml標籤 描述
BitmapDrawable 表示一張圖片,與直接引用原始圖片相比能夠設置一些效果
ShapeDrawable 經過顏色構造各類形狀的圖形,標籤對應的實體類實際是GradientDrawable
LayerDrawable 表示一種層次化的Drawable集合,能夠將不一樣的Drawable放置在不一樣的層上達到疊加效果
StateListDrawable 表示一種Drawable集合,集合中每一個Drawable對應着View的一種狀態,最經常使用於Button
LevelListDrawable 表示一種Drawable集合,集合中每一個Drawable(item)都有一個等級(level)的概念。能夠根據不一樣的等級切換對應的Drawable。每一個Drawable(item)對應一個等級範圍,能夠經過Drawable的setLevel方法來切換,若是用做ImageView的前景,還能夠經過ImageView的setImageLevel方法來切換Drawable。level範圍0-10000。
TransitionDrawable 用於實現兩個Drawable之間的淡入淡出效果,經過該Drawable中的startTransition和reverseTransition方法實現淡入淡出和逆過程,兩個方法接收一個時間參數。
InsetDrawable 能夠將其餘Drawable內嵌到本身當中,而且能夠在四周流出必定的距離。當一個View但願背景比本身實際區域小的時候,能夠用這個Drawable。LayerDrawable能夠實現相同的效果
ScaleDrawable 能夠根據本身的等級將指定的Drawable縮放到必定的比例。
ClipDrawable 根據本身當前的等級來裁剪另外一個Drawable,裁剪方向能夠經過android:clipOrientation和android:gravity兩個屬性共同控制。



2、各類Drawable的xml屬性詳解

1.

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="圖片資源id"
    android:antialias="true|false" 
    android:dither="true|false"
    android:filter="true|false"
    android:gravity="..."
    android:mipMap="true|false"
    android:tileMode="disabled|clamp|repeat|mirror" />

antialias抗鋸齒,開啓後會讓圖片變得平滑,同時也會在必定程度上下降圖片的清晰度,可是下降的幅度低至能夠忽略,因此應該開啓;
dither抖動效果,當圖片的像素配置與手機屏幕的像素配置不一致時,開啓這個選項可讓高質量圖片在低質量的屏幕上還能保持較好的顯示效果,好比圖片的色彩模式爲ARGB8888,可是設備屏幕所支持的色彩模式爲RGB555,這時候開啓抖動選項可讓圖片顯示不會過於失真,在Android中建立Bitmap通常會選用ARGB8888這個模式,在這種色彩模式下一個像素所佔的大小爲4個字節,一個像素的位數總和越高,圖像也就越逼真。根據分析,抖動效果應該開啓;
filter過濾效果,當圖片尺寸被拉伸或壓縮時,過濾能夠保持較好的顯示效果,應該開啓;
mipMap一種圖像處理技術,不經常使用,默認false便可;
titleMode平鋪模式。學習

點9圖片對應NinePatchDrawable,xml標籤是 code

2.

<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle|oval|line|ring">
    <corners
        android:radius="integer"
        android:topLeftRadius="integer"
        android:topRightRadius="integer"
        android:bottomLeftRadius="integer"
        android:bottomRightRadius="integer" />
    <gradient
        android:angle="integer"
        android:centerX="integer"
        android:centerY="integer"
        android:centerColor="color"
        android:endColor="color"
        android:gradientRadius="integer"
        android:startColor="color"
        android:type="linear|radial|sweep"
        android:useLevel="true|false" />
    <padding
        android:left="integer"
        android:top="integer"
        android:right="integer"
        android:bottom="integer" />
    <size
        android:width="integer"
        android:height="integer" />
    <solid
        android:color="color" />
    <stroke
        android:width="integer"
        android:color="color"
        android:dashWidth="integer"
        android:dashGap="integer" />
</shape>

android:shape圖形形狀,四個選項:rectangle(矩形)、oval(橢圓)、line(橫線)、ring(圓環)。默認是矩形,line和ring必須經過 標籤來指定線的寬度和顏色等信息,不然沒法達到預期的顯示效果。
針對ring這個形狀,有5個特殊屬性:
android:innerRadius 內環半徑,與android:innerRadiusRatio同時存在時,以android:innerRadius爲準
android:thickness 圓環厚度,即外半徑減去內半徑的大小,與android:thicknessRatio同時存在時以android:thickness爲準
android:innerRadiusRatio 內半徑佔整個Drawable的寬度比例,默認值9。若是是n,那麼內半徑=寬度/n
android:thicknessRatio 厚度佔整個Drawable的寬度比例,默認值3。若是是n,那麼厚度=寬度/n
android:useLevel 通常都應該使用false,不然有可能沒法達到預期效果,除非被看成LevelListDrawable來使用
xml

表示四個角的角度,只適用於shape,這裏的角度指的是圓角的程度,用px來表示,5個屬性:
android:radius 四個角同時設定相同的角度,優先級較低,會被其餘4個屬性覆蓋。
android:topLeftRadius 左上角
android:topRightRadius 右上角
android:bottomLeftRadius 左下角
android:bottomRightRadius 右下角對象

表示漸變色,與 純色標籤互斥,屬性以下:
android:angle 漸變的角度,影響漸變方向,默認爲0,值必須是45的倍數,好比0表示從左到右,90表示從上到下
android:centerX 漸變中心點的橫座標
android:centerY 漸變中心點的縱座標,漸變的中心點影響漸變的具體效果
android:startColor 漸變的起始色
android:centerColor 漸變的中間色
android:endColor 漸變的結束色
android:gradientRadius 漸變半徑,僅當type=radial時有效
android:type 漸變類別,有三個值:linear(線性漸變)、radial(徑向漸變)、sweep(掃描線漸變)。默認是線性漸變。
android:useLevel 通常爲false,看成爲StateListDrawable使用時爲true
圖片

純色填充,屬性android:color表示填充顏色ip

Shape的描邊,屬性以下:
android:width 描邊的寬度,越大shape的邊緣性看起來越粗
android:color 描邊的顏色
android:dashWidth 組成虛線的線段的寬度
android:dashGap 組成虛線的線段之間的間隔
android:dashWidth和android:dashGap有一個爲0,那麼虛線效果不生效。utf-8

表示包含它的View的空白,有上下左右四個屬性。資源

shape的大小,但不是shape最終的大小由於shape通常會自適應View的寬高。開發

3.

<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable=""
        android:id=""
        android:top=""
        android:right=""
        android:bottom=""
        android:left="" />
</layer-list>

一個layer-list能夠包含多個item,每一個item表示一個Drawable。
android:top android:right android:bottom android:left設置上下左右的偏移量。
android:drawable 直接引用一個Drawable資源,也能夠在item中自定義Drawable。
默認狀況layer-list中的全部Drawable都會被縮放至View的大小

4.

<selector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:constantSize="true|false"
    android:dither="true|false"
    android:variablePadding="true|false"
    >
    <item
        android:drawable=""
        android:state_pressed="true|false"
        android:state_focused="true|false"
        android:state_hovered="true|false"
        android:state_selected="true|false"
        android:state_checkable="true|false"
        android:state_checked="true|false"
        android:state_enabled="true|false"
        android:state_activated="true|false"
        android:state_window_focused="true|false"
        />
</selector>

android:constantSize屬性表示StateListDrawable的固有大小是否不隨狀態的改變而改變,由於狀態的改變會致使切換到具體的Drawable,而不一樣狀態的Drawable可能大小不一樣。true表示固有大小保持不變。dither表示抖動效果。android:variablePadding表示StateListDrawable的padding是否隨狀態的改變而改變,不建議開啓。

每一個item都表示一種狀態下的Drawable信息。常見狀態以下:
android:state_pressed 按下狀態
android:state_focused 獲取焦點
android:state_selected 用戶選擇了View
android:state_checked 用戶選中了View,通常用於CheckBox這類在選中和非選中狀態之間切換的View
android:state_enabled View處於可用狀態

系統會根據View的狀態從selector中選擇對應的item,按照從上到下的順序查找,直至查找到第一個匹配的item。通常默認的item都應該放在selector的最後一條而且不附帶任何狀態,這樣當上面的item都沒法匹配View的當前狀態時,就會選擇默認的item,由於默認的item不附帶狀態,因此它能夠匹配View的任何狀態。

5.

<level-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable=""
        android:minLevel=""
        android:maxLevel="" />
</level-list>

示例代碼

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@drawable/s1" android:minLevel="0" android:maxLevel="20"/>
    <item android:drawable="@drawable/s2" android:minLevel="21" android:maxLevel="40"/>
    <item android:drawable="@drawable/s3" android:minLevel="41" android:maxLevel="60"/>
    <item android:drawable="@drawable/s4" android:minLevel="61" android:maxLevel="100"/>
</level-list>
//id是level_list_img的ImageView用上面的level-list作背景
ImageView iv = (ImageView) findViewById(R.id.level_list_img); 
LevelListDrawable levelListDrawable = (LevelListDrawable) iv.getDrawable(); 

int level = ???; //業務邏輯得出一個level信息,好比當前電量
levelListDrawable.setLevel(level); //根據得出的電量level信息顯示level-list中的相應電量的圖片

6.

<transition xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable=""
        android:id=""
        android:left=""
        android:top=""
        android:right=""
        android:bottom="" />
</transition>

兩個Drawable之間的淡入淡出效果,屬性同前面的Drawable,示例代碼:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:drawable="@drawable/drawable1"/>
    <item android:drawable="@drawable/drawable2"/>
</transition>
//id是text_view的TextView用上面的transition作背景
TextView tv = (TextView) findViewById(R.id.text_view); 
TransitionDrawable drawable = (TransitionDrawable) tv.getDrawable(); 

drawable.startTransition(1000);
//drawable.reverseTransition(1000);//逆過程

7.

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable=""
    android:insetLeft=""
    android:insetTop=""
    android:insetRight=""
    android:insetBottom="" />

將其餘drawable內嵌到inset中,而且能夠在四周留出必定的間距,屬性和前面的Drawable相似。下面的示例代碼實現了inset中的shape距離View的邊界爲15dp,layer-list能夠實現相同效果:

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetBottom="15dp"
    android:insetLeft="15dp"
    android:insetRight="15dp"
    android:insetTop="15dp">

    <shape android:shape="rectangle">
        <solid android:color="#ff0000"/>
    </shape>
    
</inset>

8.

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable=""
    android:scaleGravity=""
    android:scaleHeight=""
    android:scaleWidth="" />

android:scaleGravity等同於shape中的android:gravity,android:scaleWidth和android:scaleHeight分別表示對指定drawable寬和高的縮放比例,以百分比的形式表示(看下面的示例代碼)。使用scale的時候須要考慮ScaleDrawable的level值,levle是0的時候表示ScaleDrawable不可見,0也是默認值,因此要想ScaleDrawable可見,level等級不能是0。示例代碼以下:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/test_drawable"
    android:scaleGravity="center"
    android:scaleHeight="70%"
    android:scaleWidth="70%" />
View view = findViewById(R.id.test_view);
ScaleDrawable drawable = (ScaleDrawable)view.getBackground();
drawable.setLevel(1);

代碼中必須設置level值,不然默認值0是不可見的。level範圍系統內部約定爲0-10000,固然設置成20000也能正常工做但不推薦那樣作。

9.

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable=""
    android:clipOrientation=""
    android:gravity="" />

clipOrientation表示裁剪方向,有水平和豎直兩個方向。gravity和clipOrientation一塊兒才能發揮做用,gravity的值以下:

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

Drawable等級是有範圍的,即0-10000,最小值0表示徹底裁剪,即整個Drawable都不可見。最大值10000表示不裁剪。若是豎直方向從上向下裁剪,level值是8000表示裁剪了2000,即在頂部裁剪掉20%的區域,被裁剪的區域就至關於不存在了。



3、Drawable的 level 總結

上面xml屬性介紹中有些drawable中level是很重要的,這裏總結一下:

  • 中有多個item,每一個item對應一個drawable,經過設置具體的level值來決定使用哪一個item即drawable。
  • 用於縮放,level默認值是0,0表示ScaleDrawable不可見,因此要想ScaleDrawable可見,必須設置level不爲0,具體是幾無所謂,不爲0便可
  • 表示裁剪,level值決定裁剪百分比,須要具體值,由於決定裁剪百分比

level值的範圍系統規定0-10000,設置level值的方法:

  1. 將相應的Drawable設置成一個View的背景
  2. 從View的背景中取得相應Drawable對象,代碼view.getDrawable() 或 view.getBackground(),強轉成相應的Drawable類型便可
  3. 取得Drawable對象後調用setLevel()方法設置level。
相關文章
相關標籤/搜索