Drawable
Drawable,Bitmap檩坚,Canvas着撩,View之間的關(guān)系
Bitmap是一種像素存儲介質(zhì),圖像最終要保存下來要通過它剩檀。Canvas則是繪圖工具憋沿,提供了2D的繪圖方法旺芽,方便我們繪圖沪猴。View是一種容器,裝在Bitmap采章,將其呈現(xiàn)出來运嗜。Drawable:Android把可繪制的圖像抽象成了Drawable,封裝了一系列繪圖時需要做的工作(例如設(shè)定角度悯舟、長度担租、大小、顏色)抵怎,最后在draw()方法中用Canvas以及Bitmap繪制奋救。那么有了疑問既然Canvas能完成繪圖的工作和必要Drawable呢岭参?其實繪圖還需要Paint,來設(shè)置畫筆的顏色尝艘,尺寸等屬性演侯。Drawable相當(dāng)于一個框架,集合了繪圖的一些列工作(Paint背亥,Canvas秒际,Bitmap),封裝起來狡汉,方便開發(fā)者使用娄徊。
Drawable類型
Android內(nèi)置了如下幾種Drawable類型:ColorDrawable、GradientDrawable盾戴、BitmapDrawable寄锐、 NinePatchDrawable、InsetDrawable尖啡、ClipDrawable锐峭、ScaleDrawable、RotateDrawable可婶、AnimationDrawable沿癞、LayerDrawable、LevelListDrawable矛渴、StateListDrawable椎扬、TransitionDrawable
在實際的開發(fā)過程中,會把使用到的資源都放置在res/drawable目錄具温,AndroidStudio會把該目錄下的資源在項目R文件中生成相應(yīng)的id蚕涤。當(dāng)需要使用圖片資源的時候,可以使用@drawable標(biāo)志在xml中引用drawable資源铣猩,也可以在代碼中使用id引用這些drawable資源揖铜。
drawable是內(nèi)存共享的,也就是說不同地方使用同一個id达皿,指向的是同一個drawable資源天吓,具有相同的狀態(tài)。當(dāng)改變drawable資源的狀態(tài)峦椰,引用該資源的地方都會改變龄寞。
ColorDrawable
ColorDrawable 是最簡單的Drawable,它實際上是代表了單色可繪制區(qū)域汤功,它包裝了一種固定的顏色物邑,當(dāng)ColorDrawable被繪制到畫布的時候會使用顏色填充Paint,在畫布上繪制一塊單色的區(qū)域。
XML
<?xml version="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@android:color/holo_blue_light">
</color>
在xml文件中使用color作為根節(jié)點來創(chuàng)建ColorDrawable色解,它只有一個android:color屬性茂嗓,通過它來決定ColorDrawable的顏色,Android并沒有提供修改這個顏色值的Api科阎,所以這個顏色一旦設(shè)置之后在抛,就不能直接修改了。
我們也可以通過java代碼來創(chuàng)建ColorDrawable對象萧恕。Android中使用一個int類型的數(shù)據(jù)表示顏色值刚梭,通常習(xí)慣使用十六進(jìn)制格式的數(shù)據(jù)表示顏色值。一個int類型包含四個字節(jié)票唆,分別代表顏色的4個組成部分:透明度(Alpha)朴读、紅(RED)、綠(GREEN)走趋、藍(lán)(BLUE)衅金,每個部分由一個字節(jié)(8個bit)表示,取值范圍為0~255簿煌。在xml中使用顏色時可以省略透明度(Alpha)部分氮唯,如#ff0000表示紅色。但是在代碼中必須要明確指出透明度(Alpha)代表的數(shù)據(jù)姨伟,如果省略了就表示完全透明的顏色惩琉,例如0xFFFF0000表示紅色,而0xFF0000雖然也表示紅色夺荒,但它卻是完全透明的瞒渠,也就是說當(dāng)繪制到畫布上時,看不出有任何效果技扼。
java
ColorDrawable drawable = new ColorDrawable(0xffff0000);
GradientDrawable
GradientDrawable 表示一個漸變區(qū)域伍玖,可以實現(xiàn)線性漸變、發(fā)散漸變和平鋪漸變效果剿吻,在Android中可以使用GradientDrawable表示很多復(fù)雜而又絢麗的界面效果窍箍。
在xml文件中使用shape作為根節(jié)點來創(chuàng)建GradientDrawable,它包含很多屬性和子節(jié)點:
shape屬性是形狀定義丽旅,通過android:shape屬性指定:
- rectangle: 矩形椰棘,默認(rèn)的形狀,可以畫出直角矩形魔招、圓角矩形晰搀、弧形等
- oval: 橢圓形五辽,用得比較多的是畫正圓
- line: 線形办斑,可以畫實線和虛線
- ring: 環(huán)形,可以畫環(huán)形進(jìn)度條
shape還有一些特定場合的屬性,適用于android:shape屬性指定為ring時生效:
- android:innerRadius 內(nèi)環(huán)的半徑
- android:innerRadiusRatio 浮點型乡翅,以環(huán)的寬度比率來表示內(nèi)環(huán)的半徑鳞疲,默認(rèn)為3,表示內(nèi)環(huán)半徑為環(huán)的寬度除以3蠕蚜,該值會被android:innerRadius覆蓋
- android:thickness 環(huán)的厚度
- android:thicknessRatio 浮點型尚洽,以環(huán)的寬度比率來表示環(huán)的厚度,默認(rèn)為9靶累,表示環(huán)的厚度為環(huán)的寬度除以9腺毫,該值會被android:thickness覆蓋
- android:useLevel 一般為false,否則可能環(huán)形無法顯示挣柬,只有作為LevelListDrawable使用時才設(shè)為true
子節(jié)點有:
-
solid: 設(shè)置形狀填充的顏色潮酒,只有android:color一個屬性
android:color 填充的顏色
-
padding: 設(shè)置內(nèi)容與形狀邊界的內(nèi)間距,可分別設(shè)置左右上下的距離
- android:left 左內(nèi)間距
- android:right 右內(nèi)間距
- android:top 上內(nèi)間距
- android:bottom 下內(nèi)間距
-
gradient: 設(shè)置形狀的漸變顏色邪蛔,可以是線性漸變急黎、輻射漸變、掃描性漸變
- android:type 漸變的類型
- linear 線性漸變侧到,默認(rèn)的漸變類型
- radial 放射漸變勃教,設(shè)置該項時,android:gradientRadius也必須設(shè)置
- sweep 掃描性漸變
- android:startColor 漸變開始的顏色
- android:endColor 漸變結(jié)束的顏色
- android:centerColor 漸變中間的顏色
- android:angle 漸變的角度匠抗,線性漸變時才有效故源,必須是45的倍數(shù),0表示從左到右汞贸,90表示從下到上
- android:centerX 漸變中心的相對X坐標(biāo)心软,放射漸變時才有效,在0.0到1.0之間著蛙,默認(rèn)為0.5删铃,表示在正中間
- android:centerY 漸變中心的相對X坐標(biāo),放射漸變時才有效踏堡,在0.0到1.0之間猎唁,默認(rèn)為0.5,表示在正中間
- android:gradientRadius 漸變的半徑顷蟆,只有漸變類型為radial時才使用
- android:useLevel 如果為true诫隅,則可在LevelListDrawable中使用
- android:type 漸變的類型
-
corners: 設(shè)置圓角,只適用于rectangle類型帐偎,可分別設(shè)置四個角不同半徑的圓角逐纬,當(dāng)設(shè)置的圓角半徑很大時,比如200dp削樊,就可變成弧形邊了
- android:radius 圓角半徑豁生,會被下面每個特定的圓角屬性重寫
- android:topLeftRadius 左上角的半徑
- android:topRightRadius 右上角的半徑
- android:bottomLeftRadius 左下角的半徑
- android:bottomRightRadius 右下角的半徑
-
stroke: 設(shè)置描邊兔毒,可描成實線或虛線。
- android:color 描邊的顏色
- android:width 描邊的寬度
- android:dashWidth 設(shè)置虛線時的橫線長度
- android:dashGap 設(shè)置虛線時的橫線之間的距離
-
size: 設(shè)置形狀默認(rèn)的大小甸箱,可設(shè)置寬度和高度
- android:width 寬度
- android:height 高度
實例XML:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- shape可以定義四種形狀的drawable,矩形,橢圓形,線性,環(huán)形.默認(rèn)矩形-->
<!--指定形狀的填充色,唯一屬性color-->
<solid android:color="@android:color/holo_blue_light"/>
<gradient
android:type="linear"
android:startColor="#E3F2FD"
android:centerColor="#90CAF9"
android:endColor="#0D47A1"
android:angle="0"/>
<!-- 設(shè)置內(nèi)邊距-->
<padding
android:bottom="12dp"
android:left="12dp"
android:right="12dp"
android:top="12dp"/>
<!-- corners設(shè)置圓角育叁,只適用于rectangle -->
<corners android:radius="200dp"/>
<!-- stroke設(shè)置drawable邊框
width設(shè)置變寬寬度
color設(shè)置邊框顏色
dashGap設(shè)置虛線段的間隔
dashWidth設(shè)置虛線段的長度-->
<stroke
android:width="2dp"
android:color="@android:color/darker_gray"
android:dashGap="4dp"
android:dashWidth="4dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<!-- android:gradientRadius 漸變的半徑,只有漸變類型為radial時才使用 -->
<gradient
android:type="radial"
android:startColor="@android:color/holo_blue_light"
android:endColor="@android:color/holo_red_light"
android:centerColor="@android:color/holo_green_light"
android:gradientRadius="50dp"
android:centerX="1"
android:centerY="0.8"
/>
<padding
android:bottom="4dp"
android:top="4dp"
android:right="4dp"
android:left="4dp"/>
<size
android:width="60dp"
android:height="60dp"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<!-- line主要用于畫分割線芍殖,是通過stroke和size特性組合 -->
<!-- 實際顯示的線 -->
<stroke
android:width="1dp"
android:color="@android:color/black"
android:dashGap="3dp"
android:dashWidth="8dp"/>
<!-- 形狀的高度-->
<size
android:height="4dp"/>
<!-- 這里需要注意:
只能夠畫水平線;
線的高度由stroke節(jié)點的android:width屬性指定;
形狀的高度由size節(jié)點的android:height屬性指定,
其值必須大于stroke節(jié)點的android:width的,
否則線將無法顯示;
線在形狀中時居中的;
引用虛線的view需要添加屬性android:layerType豪嗽,
值設(shè)為"software",否則顯示不了虛線豌骏。
-->
</shape>
當(dāng)android:shape屬性制定為ring時龟梦,在shape跟節(jié)點中有一些特定的屬性生效:
- android:innerRadius 內(nèi)環(huán)的半徑
- android:innerRadiusRatio 浮點型,以環(huán)的寬度比率來表示內(nèi)環(huán)的半徑窃躲,默認(rèn)為3变秦,表示內(nèi)環(huán)半徑為環(huán)的寬度除以3,該值會被android:innerRadius覆蓋
- android:thickness 環(huán)的厚度
- android:thicknessRatio 浮點型框舔,以環(huán)的寬度比率來表示環(huán)的厚度蹦玫,默認(rèn)為9,表示環(huán)的厚度為環(huán)的寬度除以9刘绣,該值會被android:thickness覆蓋
- android:useLevel 一般為false樱溉,否則可能環(huán)形無法顯示,只有作為LevelListDrawable使用時才設(shè)為true
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadiusRatio="4"
android:thicknessRatio="5"
android:shape="ring"
android:useLevel="false">
<!--環(huán)形的寬度是指環(huán)形drawable外面矩形的寬度,
環(huán)形的厚度指的是外徑減去內(nèi)徑的大小-->
<gradient
android:centerColor="@android:color/holo_green_light"
android:endColor="@android:color/holo_red_light"
android:startColor="@android:color/holo_blue_light"
android:type="sweep"/>
<size
android:width="60dp"
android:height="60dp"/>
</shape>
效果圖:
細(xì)說Drawable和View之間的關(guān)系
每一個View包括其子類都有一個drawable成員變量纬凤。在View.java中有一個Drawable作為背景福贞。
其實改變View圖形顯示的2D繪畫有兩種方式:
- 調(diào)用 View 及其子類提供的方法如
View:setBackground(Drawable)
,ImageView:setImageBitmap(Bitmap)
停士, 這些方法直接或間接設(shè)置相應(yīng)類中的 Drawable 私有成員挖帘。 - 繼承 View 并重載 onDraw(Canvas),回調(diào)中得到畫布 Canvas恋技,調(diào)用其一系列基本圖形的繪畫 draw 方法操作其 Bitmap 中的像素數(shù)據(jù)拇舀。
雖然第二種情況看似和drawable無關(guān),其實在View.java中的draw()方法調(diào)用了drawable.draw(canvas)將背景繪制:
public class View {
...
private Drawable mBackground; // 背景
...
public void draw(Canvas canvas) {
...
// Step 1, draw the background, if needed
if (!dirtyOpaque) {
drawBackground(canvas);
}
...
}
private void drawBackground(Canvas canvas) {
final Drawable background = mBackground;
...
background.draw(canvas);
...
}
}