Android 的 Drawable
Drawable 表示的是一種可以在 Canvas 上進行繪製的抽象概念。使用簡單,比自定義 View 的成本低;非圖片型別的 Drawable 佔用空間小,有助於減小 APK 體積。
Drawable 使用範圍單一,一個是作為 ImageView 中的影象來顯示,另外一個就是作為 View 的背景。
Drawable 簡介
在 Android 設計中,Drawable 是一個抽象類,它是所有 Drawable 的基類。
Drawable 的分類
1. BitmapDrawable
<?xml version="1.0" encoding="utf-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:antialias="true"// 是否開啟抗鋸齒 android:dither="true"// 是否開啟抖動效果,開啟後讓高質量圖片在低質量螢幕保持較好的顯示效果 android:filter="true"// 是否開啟過濾效果 android:gravity="top"// 當圖片小於容器尺寸時,可以對圖片進行定位 android:mipMap="false"// 紋理對映,一般為 false android:src="@drawable/image" // 圖片資源 id android:tileMode="disabled"// 平鋪模式,選項有 disabled、clamp、repeat 和 mirror > </bitmap>
此外,也可以用<nine-patch>
標籤來表示一張 .9 格式的圖片。
2. ShapeDrawable
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"// 表示圖形的形狀:rectangle 矩形、oval 圓形、line 橫線和 ring 圓環 > <corners// 表示四個角的角度,只適用於 rectangle 矩形 android:bottomLeftRadius="0dp" android:bottomRightRadius="15dp" android:topLeftRadius="10dp" android:topRightRadius="15dp" android:radius="16dp"// 同時為四個角設定,優先順序較低 /> <gradient// 表示漸變色,與 solid 標籤互相排斥 android:angle="0"// 漸變的角度,預設為 0 ,值必須為 45 的倍數,0 表示從左到右,90 表示從下到上 android:centerColor="#00ff00"// 漸變的中間色 android:centerX="0.5"// 漸變的中心點橫座標 android:centerY="0.5"// 漸變的中心點縱座標 android:endColor="#0000ff"// 漸變的結束色 android:startColor="#ff0000"// 漸變的起始色 android:gradientRadius="20dp"// 漸變半徑,僅當 type = radial 時有效 android:type="linear"// 漸變類別,linear 線性漸變、radial 徑向漸變、sweep 掃描線漸變/> <solid android:color="#ff0000"// 純色填充 與 gradient 標籤互相排斥 /> <stroke// 表示描邊 android:width="2dp"// 描邊的寬度 android:color="#00ff00"// 描邊的顏色 android:dashGap="2dp"// 組成虛線的線段寬度 android:dashWidth="10dp"// 組成虛線的線段之間的間隔 /> <padding android:left="20dp"// 表示包含這個 shape 的空白/> <size// 表示 shape 的大小,但作為 View 的背景時還是會被拉伸或縮小 android:width="30dp" android:height="30dp"/> </shape>
3. LayerDrawable
表示一種層次化的 Drawable 集合,下面的 item 會覆蓋上面的 item,通過合理的分層,可以實現一些特殊的疊加效果。
<?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="#0ac39e" /> </shape> </item> <item android:bottom="6dp"// 相對於 View 的上下左右偏移量> <shape android:shape="rectangle" > <solid android:color="#ffffff" /> </shape> </item> </layer-list>
4. StateListDrawable
表示的是一種 Drawable 集合,每個 Drawable 都對應著 View 的一種狀態,系統會根據 View 的狀態選擇合適的 Drawable。
<?xml version="1.0" encoding="utf-8" ?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 預設時的背景圖片--> <item android:drawable="@drawable/pic1" /> <!-- 沒有焦點時的背景圖片 --> <item android:state_window_focused="false" android:drawable="@drawable/pic1" /> <!-- 非觸控模式下獲得焦點並單擊時的背景圖片 --> <item android:state_focused="true" android:state_pressed="true"android:drawable= "@drawable/pic2" /> <!-- 觸控模式下單擊時的背景圖片--> <item android:state_focused="false" android:state_pressed="true"android:drawable="@drawable/pic3" /> <!--選中時的圖片背景--> <item android:state_selected="true" android:drawable="@drawable/pic4" /> <!--獲得焦點時的圖片背景--> <item android:state_focused="true" android:drawable="@drawable/pic5" /> </selector>
5. LevelListDrawable
表示的是一種 Drawable 集合,每個 Drawable 都有一個等級(level)的概念,根據不同等級,會切換到對應的 Drawable。
<?xml version="1.0" encoding="utf-8" ?> <level-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/on" android:maxLevel="10" android:minLevel="5"/> <item android:drawable="@drawable/off" android:maxLevel="5" android:minLevel="0"/> </level-list>
通過 Drawable 的setLevel
或 ImageView 的setImageLevel
來切換 Drawable。Level 的有效範圍是 0~10000。
6. TransitionDrawable
用於實現兩個 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>
通過startTransition
和reverseTransition
方法來實現效果。
TransitionDrawable drawable = (TransitionDrawable)textview.getBackground(); drawable.startTransition(1000);
7. InsetDrawable
可以將其他 Drawable 內嵌到自己當中,並可以在四周留出一定間距。
<?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. ScaleDrawable
它可以根據自己的等級(level)將指定的 Drawable 縮放到一定的比例。
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/image1"// 目標 drawable android:scaleHeight="70%" android:scaleWidth="70%" android:scaleGravity="center" />
ScaleDrawable drawable = (ScaleDrawable)textview.getBackground(); drawable.setlevel(1);
9. ClipDrawable
它可以根據自己的等級(level)來裁切另一個 Drawable。
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="vertical"// 表示裁切方向,只有水平和豎直兩個方向 android:drawable="@drawable/image1" android:gravity="bottom"// 與 clipOrientation 一起使用才有效果 />
ClipDrawable drawable = (ClipDrawable)textview.getBackground(); drawable.setlevel(5000);
等級越大,裁剪的區域越小,因此等級 10000 表示不裁切,而等級 0 表示裁切全部區域,圖片將不可見。
自定義 Drawable
通常沒必要去自定義 Drawable,因為無法在 XML 中去使用。下面是一個例子來實現簡單的自定義 Drawable:
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 r = getBounds(); float cx = r.exactCenterX(); float cy = r.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 cf) { mPaint.setColorFilter(cf); invalidateSelf(); } @Override public int getOpacity() { // not sure, so be safe return PixelFormat.TRANSLUCENT; } }
本章節配套原始碼ofollow,noindex">戳我