## 6.1 Drawable簡介
(1)Android的`Drawable`表示的是一種可以在`Canvas`上進行繪制的概念,它的種類很多,最常見的就是圖片和顏色了。它有兩個重要的優點:一是比自定義view要簡單;二是非圖片類型的drawable占用空間小,利于減小apk大小。
(2)Drawable是抽象類,是所有Drawable對象的基類。
(3)Drawable的內部寬/高可以通過`getIntrinsicWidth`和`getIntrinsicHeight`方法獲取,但是并不是所有Drawable都有內部寬/高。圖片Drawable的內部寬高就是圖片的寬高,但是顏色Drawable就沒有寬高的概念,它一般是作為view的背景,所以會去適應view的大小,這兩個方法都是返回-1。
## 6.2 Drawable分類
(1)BitmapDrawable和NinePatchDrawable
~~~
<?xml version="1.0" encoding="utf-8"?>
<bitmap / nine-patch
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:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />
~~~
屬性分析:
`android:antialias`:是否開啟圖片抗鋸齒功能。開啟后會讓圖片變得平滑,同時也會一定程度上降低圖片的清晰度,建議開啟;
`android:dither`:是否開啟抖動效果。當圖片的像素配置和手機屏幕像素配置不一致時,開啟這個選項可以讓高質量的圖片在低質量的屏幕上還能保持較好的顯示效果,建議開啟。
`android:filter`:是否開啟過濾效果。當圖片尺寸被拉伸或壓縮時,開啟過濾效果可以保持較好的顯示效果,建議開啟;
`android:gravity`:當圖片小于容器的尺寸時,設置此選項可以對圖片進行定位。
`android:tileMode`:平鋪模式,有四種選項`["disabled" | "clamp" | "repeat" | "mirror"]`。當開啟平鋪模式后,gravity屬性會被忽略。repeat是指水平和豎直方向上的平鋪效果;mirror是指在水平和豎直方向上的鏡面投影效果;clamp是指圖片四周的像素會擴展到周圍區域,這個比較特別。
(2)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 //當shape為rectangle時使用
android:radius="integer" //半徑值會被后面的單個半徑屬性覆蓋,默認為1dp
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<gradient //漸變
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="integer"
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 //指定大小,一般用在imageview配合scaleType屬性使用
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`:默認的shape是矩形,`line`和`ring`這兩種形狀需要通過`<stroke>`來制定線的寬度和顏色,否則看不到效果。
`gradient`:`solid`表示純色填充,而`gradient`表示漸變效果。`andoid:angle`指漸變的角度,默認為0,其值必須是45的倍數,0表示從左到右,90表示從下到上,其他類推。
`padding`:這個表示的是包含它的view的空白,四個屬性分別表示四個方向上的padding值。
`size`:ShapeDrawable默認情況下是沒有寬高的概念的,但是可以如果指定了size,那么這個時候shape就有了所謂的固有寬高,但是作為view的背景時,shape還是會被拉伸或者縮小為view的大小。
(3)LayerDrawble
對應標簽`<layer-list>`,表示層次化的Drawable集合,實現一種疊加后的效果。
屬性`android:top/left/right/bottom`表示drawable相對于view的上下左右的偏移量,單位為像素。
(4)StateListDrawable
對應標簽`<selector>`,也是表示Drawable集合,每個drawable對應著view的一種狀態。
一般來說,默認的item都應該放在selector的最后一條并且不附帶任何的狀態。
(5)LevelListDrawable
對應標簽`<level-list>`,同樣是Drawable集合,每個drawable還有一個`level`值,根據不同的level,LevelListDrawable會切換不同的Drawable,level值范圍從0到100000。
(6)TransitionDrawable
對應標簽`<transition>`,它用于是吸納兩個Drawable之間的淡入淡出效果。
~~~
<transition xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/shape_drawable_gradient_linear"/>
<item android:drawable="@drawable/shape_drawable_gradient_radius"/>
</transition>
TransitionDrawable drawable = (TransitionDrawable) v.getBackground();
drawable.startTransition(5000);
~~~
(7)InsetDrawable
對應標簽`<inset>`,它可以將其他drawable內嵌到自己當中,并可以在四周留出一定的間距。當一個view希望自己的背景比自己的實際區域小的時候,可以采用InsetDrawable來實現。
~~~
<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)ScaleDrawable
對應標簽`<scale>`,它可以根據自己的level將指定的Drawable縮放到一定比例。如果level越大,那么內部的drawable看起來就越大。
(9)ClipDrawable
對應標簽`<clip>`,它可以根據自己當前的level來裁剪另一個drawable,裁剪方向由`android:clipOrientation`和`andoid:gravity`屬性來共同控制。level越大,表示裁剪的區域越小。
~~~
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="@drawable/image1"
android:gravity="bottom" />
~~~
## 6.3 自定義Drawable
(1)Drawable的工作核心就是`draw`方法,所以自定義drawable就是重寫`draw`方法,當然還有`setAlpha`、`setColorFilter`和`getOpacity`這幾個方法。當自定義Drawable有固有大小的時候最好重寫`getIntrinsicWidth`和`getIntrinsicHeight`方法。
(2)Drawable的內部大小不等于Drawable的實際區域大小,Drawable的實際區域大小可以通過它的`getBounds`方法來得到,一般來說它和view的尺寸相同。
其他學習資料:
1.[Android樣式的開發:shape篇](http://keeganlee.me/post/android/20150830)
2.[Android樣式的開發:drawable篇](http://keeganlee.me/post/android/20150916)
3.[Android樣式的開發:selector篇](http://keeganlee.me/post/android/20150905)
4.[Android樣式的開發:layer-list篇](http://keeganlee.me/post/android/20150909)
- 前言
- 讀書筆記(1)第1章 Activity的生命周期和啟動模式
- 讀書筆記(2)第2章 IPC機制
- 讀書筆記(3)第3章 View的事件體系
- 讀書筆記(4)第4章 View的工作原理
- 讀書筆記(5)第5章 理解RemoteViews
- 讀書筆記(6)第6章 Android的Drawable
- 讀書筆記(7)第7章 Android動畫深入分析
- 讀書筆記(8)第8章 理解Window和WindowManager
- 讀書筆記(9)第9章 四大組件的工作過程
- 讀書筆記(10)第10章 Android的消息機制
- 讀書筆記(11)第11章 Android的線程和線程池
- 讀書筆記(12)第12章 Bitmap的加載和Cache
- 讀書筆記(13)第13章 綜合技術