Drawable

一愁溜、概念

Drawable有很多種罐栈,它們都表示一種圖像的概念咕缎,但是它們又不全是圖片珠十,通過顏色也可以構造出各式各樣的圖像的效果。在實際開發(fā)中凭豪,Drawable常被用來作為View的背景使用焙蹭。Drawable一般都是通過XML來定義的,也可以通過代碼來創(chuàng)建嫂伞,用代碼創(chuàng)建會稍顯復雜孔厉。

Drawable的內部寬/高可以通過getIntrinsicWidth和getIntrinsicHeight這兩個方法來獲取,但是并不是所有的Drawable都有內部寬/高末早,比如一張圖片所形成的Drawable烟馅,它的內部寬/高就是圖片的寬/高,但是一個顏色所形成的Drawable就沒有寬/高的概念然磷。另外需要注意的是郑趁,Drawable的內部寬/高不等同于它的實際大小,當用作View的背景時姿搜,Drawable會被拉伸至View的同等大小寡润。

二、分類

1.BitmapDrawable

在實際開發(fā)中舅柜,我們可直接引用原始的圖片梭纹,也可通過XML的方式來描述它。
通過XML來描述的BitmapDrawable可以設置更多的效果致份,如下:

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:antialias="[true | false]"
    android:dither="[true | false]"
    android:filter="[true | false]"
    android:gravity="[top | bottom | left | right |
     center_vertical | fill_vertical | center_horizontal |
      fill_horizontal | center | fill |
       clip_vertical | clip_horizontal]"
    android:mipMap="[true | false]"
    android:tileMode="[disabled | clamp | repeat | mirror]" />

android:src:圖片的資源id变抽。
android:antialias:是否開啟圖片抗鋸齒。開啟后會讓圖片變得平滑,同時也會一定程度上降低圖片的清晰度绍载。
android:dither:是否開啟抖動效果诡宗。開啟后可讓高質量的圖片在低質量的屏幕上能保持較好的顯示效果。
android:filter:是否開啟過濾效果击儡。當圖片尺寸被拉伸或壓縮時塔沃,開啟過濾效果可保持較好的顯示效果。
android:gravity:當圖片小于容器的尺寸時阳谍,設置此屬性對圖片進行定位蛀柴。此屬性的可選項較多,也可用|來組合使用矫夯。
android:mipMap:是否開啟紋理映射鸽疾。
android:tileMode:平鋪模式。

2.NinePatchDrawable

表示一張.9格式的圖片茧痒。.9圖片可自動地根據(jù)所需的寬/高進行相應的縮放并保證不失真肮韧。
在實際使用中可以直接引用.9圖片,也可以通過XML來描述它旺订。
通過XML描述如下:

<?xml version="1.0" encoding="utf-8"?>
<nine-patch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:dither="[true | false]" />

android:src:圖片的資源id弄企。
android:dither:是否開啟抖動效果。開啟后可讓高質量的圖片在低質量的屏幕上能保持較好的顯示效果区拳。

3.ShapeDrawable

可以理解為通過顏色來構造的圖形拘领,既可以是純色的圖形,也可以是具有漸變效果的圖形樱调。

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="[rectangle | oval | line | ring]"
    <corners
        android:radius="integer"
        android:topLeftRaidus="integer"
        android:topRightRaidus="integer"
        android:bottomLeftRaidus="integer"
        android:bottomRightRaidus="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" />

android:shape:圖形的形狀约素,有四個選項:rectangle(矩形)、oval(橢圓)笆凌、line(橫線)和ring(圓環(huán))圣猎,默認是rectangle。另外line和ring必須通過<stroke>標簽來指定線的寬度和顏色等信息乞而,否則無法達到預期的顯示效果送悔。
<corners>:表示shape的四個圓角的角度,只適用于矩形爪模,屬性如下:
android:radius:為四個角同事設定相同的角度欠啤。優(yōu)先級比以下4個屬性要低。
android:topLeftRadius:左上角的角度屋灌。
android:topRightRadius:右上角的角度洁段。
android:bottomLeftRadius:左下角的角度。
android:bottomRightRadius:右下角的角度共郭。
<solid>:純色填充祠丝,通過android:color指定填充的顏色疾呻。
<gradient>:漸變效果,與<solid>純色填充是互相排斥的纽疟,屬性如下:
android:angle:漸變的角度罐韩。默認為0憾赁,其值必須為45的倍數(shù)污朽。此角度會影響漸變的方向,0表示從左到右龙考,90表示從下到上蟆肆。
android:centerX:漸變的中心點的X坐標。
android:centerY:漸變的中心點的Y坐標晦款。
android:startColor:漸變的起始色炎功。
android:centerColor:漸變的中間色。
android:endColor:漸變的結束色缓溅。
android:gradient:漸變半徑蛇损。僅當android:type="radial"時有效。
android:useLevel:一般為false坛怪,當Drawable作為StateListDrawable時為true淤齐。
android:type:漸變的類別。有l(wèi)inear(線性漸變)袜匿、radial(徑向漸變)更啄、sweep(掃描線漸變),默認為linear居灯。
<stroke>:描邊祭务。
android:width:描邊的寬度。
android:color:描邊的顏色怪嫌。
android:dashWidth:虛線的寬度义锥。
android:dashGap:虛線之間的間隔。
<padding>:空白岩灭,表示的不是shape的空白拌倍,而是包含它的View的空白,有l(wèi)eft川背、top贰拿、right、bottom四個屬性熄云。
<size>:大小膨更。有兩個屬性:android:width和android:height,分別表示shape的內部寬/高缴允,但是一般來說它并不是shape最終顯示的大小荚守。也就是說珍德,通過<size>標簽可以設置ShapeDrawable的內部寬/高,但是作為View的背景時矗漾,shape還會被拉伸或者縮小為View的大小锈候。

4.LayerDrawable

對應<layer-list>標簽,表示一種層次化的Drawable集合敞贡,通過將不同的Drawable放置在不同的層上面從而達到一種疊加后的效果泵琳。

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
    <!-- 其他item -->
</layer-list>

一個layer-list可包含多個item,每個item表示一個Drawable誊役』窳校可在android:drawable中引用一個現(xiàn)有的Drawable資源,也可在<item>中自定義Drawable蛔垢。
默認情況下击孩,layer-list中的所有Drawable都會被縮放至View的大小∨羝幔可設置Drawable相對于View的上下左右偏移量巩梢。另外對于bitmap,需要使用其android:gravity來控制圖片的顯示效果艺玲。
layer-list有層次的概念括蝠,下面的item會覆蓋上面的item。通過合理的分層板驳,可實現(xiàn)一些特殊的疊加效果又跛。

5.StateListDrawable

對應<selector>標簽,表示一個Drawable的集合若治。每個Drawable對應著View的一種狀態(tài)慨蓝,系統(tǒng)會根據(jù)View的狀態(tài)來選擇合適的Drawable。StateListDrawable主要用于設置可單擊的View的背景端幼,最常見的是Button礼烈。

<?xml version="1.0" encoding="utf-8"?>
<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="@[package:]drawable/drawable_resource"
        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]" />
    <!-- 其他item -->
</selector>

android:constantSize:StateListDrawable的內部寬/高是否不隨著其狀態(tài)的改變而改變,因為狀態(tài)的改變會導致StateListDrawable切換到具體的Drawable婆跑,而不同的Drawable具有不同的內部寬/高此熬。默認為false,即隨著狀態(tài)的改變而改變大小滑进。若為true犀忱,則表示其內部所有Drawable的內部寬/高的最大值。
android:dither:是否開啟抖動效果扶关。開啟此選項可以讓圖片在低質量的屏幕上仍然獲得較好的顯示效果阴汇。此選項默認值為true。
android:variblePadding:StateListDrawable的padding是否隨著其狀態(tài)的改變而改變节槐。默認為false搀庶,表示其內部所有Drawable的padding的最大值拐纱。若為true,表示會隨著狀態(tài)的改變而改變哥倔。
<item>:表示某種狀態(tài)下的一個具體的Drawable秸架。用android:drawable指定一個現(xiàn)有Drawable的資源id,剩下的屬性表示的是View的各種狀態(tài)咆蒿。
系統(tǒng)會按照從上到下的順序查找东抹,直至查找到第一條匹配的item。一般來說蜡秽,默認的item都應該放在selector的最后一條府阀,并且不附帶任何的狀態(tài)。

6.LevelListDrawable

對應<level-list>標簽芽突,表示一個Drawable集合,集合中的每個Drawable都有一個等級的概念董瞻。根據(jù)不同的等級寞蚌,LevelListDrawable會切換為對應的Drawable。

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:maxLevel="integer"
        android:minLevel="integer" />
    <!-- 其他item -->
</level-list>

7.TransitionDrawable

對應于<transition>標簽钠糊,用于實現(xiàn)兩個Drawable之間的淡入淡出效果挟秤。

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
    <!-- 另一個item,注意transition只包含兩個item -->
</transition>

常將TransitionDrawable作為View的背景抄伍,再調用它的startTransition和reverseTransition方法來實現(xiàn)淡入淡出效果以及它的逆過程艘刚。代碼如下:

ImageView imageview = (ImageView) findViewById(R.id.imageview);
TransitionDrawable drawable = (TransitionDrawable) imageview.getBackground();
drawable.startTransition(1000);

8.InsetDrawable

對應<inset>標簽,可將其他Drawable內嵌到自己當中截珍,并可在四周留出一定的間距攀甚。當一個View希望自己的背景比自己的實際區(qū)域小的時候,可采用InsetDrawable來實現(xiàn)岗喉,同時我們知道秋度,通過LayoutDrawable也可以實現(xiàn)這種效果。

<?xml version="1.0" encoding="utf-8"?>
<inset 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@[package:]drawable/drawable_resource"
    android:inset="dimension"
    android:insetTop="dimension"
    android:insetRight="dimension"
    android:insetBottom="dimension"
    android:insetLeft="dimension" />

9.ScaleDrawable

對應<scale>標簽钱床,將Drawable縮放到一定比例荚斯。

<?xml version="1.0" encoding="utf-8"?>
<scale 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@[package:]drawable/drawable_resource"
    android:scaleGravity="[top | bottom | left | right |
        center_vertical | center_horizontal | center |
        fill_vertical | fill_horizontal | fill |
        clip_vertical | clip_horizontal]"
    android:scaleWidth="percentage"
    android:scaleHeight="percentage" />

縮放比例越大,內部的Drawable就越胁榕啤事期;level越大,內部的Drawable就越大纸颜。
由于level默認為0兽泣,若level為0時,ScaleDrawable不可見懂衩。

10.ClipDrawable

對應<clip>標簽撞叨,用來裁剪另一個Drawable金踪。

<?xml version="1.0" encoding="utf-8"?>
<clip 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@[package:]drawable/drawable_resource"
    android:clipOrientation="[vertical | horizontal]"
    android:gravity="[top | bottom | left | right |
        center_vertical | center_horizontal | center |
        fill_vertical | fill_horizontal | fill |
        clip_vertical | clip_horizontal]" />

android:clipOrientation:表示裁剪方向,可選為水平和豎直牵敷。
android:gravity:表示對齊方式胡岔,需要和clipOrientation一起發(fā)揮作用。
ClipDrawable的裁剪程度由level控制枷餐,調用setLevel方法可修改此值靶瘸。其取值范圍為0~10000。0表示完全裁剪毛肋,即整個Drawable都不可見怨咪;而10000表示不裁剪,即整個Drawable都可見润匙。

三诗眨、自定義Drawable

Drawable的工作原理很簡單,其核心就是draw方法孕讳。系統(tǒng)會調用Drawable的draw方法來繪制View的背景或ImageView的圖像匠楚,我們可通過重寫其draw方法來實現(xiàn)自定義Drawable。通常我們沒有必要去自定義Drawable厂财,因為無法在XML中使用自定義Drawable芋簿,這就降低了其使用范圍。

創(chuàng)建自定義Drawable璃饱,必須重寫其draw与斤、setAlpha、setColorFilter荚恶、getOpacity等方法撩穿。以下為自定義Drawable示例:

//CustomDrawable 
public class CustomDrawable extends Drawable {
    private Paint mPaint;
    
    public CustomDrawable(int color) {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(color);
    }
    
    @Override
    public void draw(Canvas canvas) {
        final Rect rect =  getBounds();
        float cx = rect.exactCenterX();
        float cy = rect.exactCenterY();
        canvas.drawCircle(cx, cy, Math.min(cx, cy), mPaint);
    }
    
    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
        invalidateSelf();
    }
    
    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
        invalidateSelf();
    }
    
    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}

//MainActivity
CustomDrawable drawable = new CustomDrawable(Color.BLUE);
imageView.setBackgroundDrawable(drawable);

若自定義的Drawable有內部寬/高時,要重寫getIntrinsicWidth和getIntrinsicHeight這兩個方法裆甩,因為它們會影響到View的wrap_content布局冗锁。
需要注意的是,Drawable的內部寬/高不等同于Drawable的實際大小嗤栓《澈樱可通過getBounds方法獲得Drawable的實際大小,一般與它的View尺寸相同茉帅。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末叨叙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子堪澎,更是在濱河造成了極大的恐慌擂错,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件樱蛤,死亡現(xiàn)場離奇詭異钮呀,居然都是意外死亡剑鞍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門爽醋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚁署,“玉大人,你說我怎么就攤上這事蚂四」飧辏” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵遂赠,是天一觀的道長久妆。 經(jīng)常有香客問我,道長跷睦,這世上最難降的妖魔是什么筷弦? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮送讲,結果婚禮上奸笤,老公的妹妹穿的比我還像新娘。我一直安慰自己哼鬓,他們只是感情好,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布边灭。 她就那樣靜靜地躺著异希,像睡著了一般。 火紅的嫁衣襯著肌膚如雪绒瘦。 梳的紋絲不亂的頭發(fā)上称簿,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天,我揣著相機與錄音惰帽,去河邊找鬼憨降。 笑死,一個胖子當著我的面吹牛该酗,可吹牛的內容都是我干的授药。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼呜魄,長吁一口氣:“原來是場噩夢啊……” “哼悔叽!你這毒婦竟也來了?” 一聲冷哼從身側響起爵嗅,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤娇澎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后睹晒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體趟庄,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡括细,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了戚啥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奋单。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虑鼎,靈堂內的尸體忽然破棺而出辱匿,到底是詐尸還是另有隱情,我是刑警寧澤炫彩,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布匾七,位于F島的核電站,受9級特大地震影響江兢,放射性物質發(fā)生泄漏昨忆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一杉允、第九天 我趴在偏房一處隱蔽的房頂上張望邑贴。 院中可真熱鬧,春花似錦叔磷、人聲如沸拢驾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽繁疤。三九已至,卻和暖如春秕狰,著一層夾襖步出監(jiān)牢的瞬間稠腊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工鸣哀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留架忌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓我衬,卻偏偏與公主長得像叹放,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子低飒,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評論 25 707
  • 一许昨、 Drawable簡介 1 Drawable表示的是一種可以在Canvas上進行繪制的抽象的概念,可以是純顏色...
    黃海佳閱讀 1,211評論 0 10
  • 概述 Android把任何可繪制在屏幕上的圖形圖像都稱為drawable 資源,你可以通過類似getDrawabl...
    小蕓論閱讀 2,720評論 2 5
  • 前言 本文是本人閱讀《Android開發(fā)藝術探索》的第6章《Android的Drawable》后的總結筆記褥赊。包含了...
    daking閱讀 5,320評論 2 29
  • 有一陣子了。 我清楚地知道速那,我需要解憂俐银。 而且重在“解”字。 那種對未來不確定的茫然感端仰,那種交流被硬生生中斷的憋堵...
    Walking林楊閱讀 576評論 1 2