Android樣式的開發:drawable彙總篇

發表於2015-11-28

Android專案重構之路:架構篇

Android專案重構之路:介面篇

Android專案重構之路:實現篇

Android技術積累:開發規範

Android樣式的開發:shape篇

Android樣式的開發:selector篇

Android樣式的開發:layer-list篇


Android有很多種drawable型別,除了前幾篇詳細講解的shapeselectorlayer-list,還有上一篇提到的color、bitmap、clip、scale、inset、transition、rotate、animated-rotate、lever-list等等,本篇文章將彙總介紹所有剩下的drawable資源。

普通圖片

圖片是最常用的drawable資源,格式包括:png(推薦)、jpg(可接受)、gif(不建議)。用圖片資源需要根據不同螢幕密度提供多張不同尺寸的圖片,它們的關係如下表:

密度分類 密度值範圍 代表解析度 圖示尺寸 圖片比例
mdpi 120~160dpi 320x480px 48x48px 1
hdpi 160~240dpi 480x800px 72x72px 1.5
xhdpi 240~320dpi 720x1280px 96x96px 2
xxhdpi 320~480dpi 1080x1920px 144x144px 3
xxxhdpi 480~640dpi 1440x2560px 192x192px 4

本來還有一個ldpi的,但現在這種小螢幕的裝置基本滅絕了,所以不需要再考慮適配。如上表所示,一套圖片一般需要提供5張不同比例的圖片。還好有切圖工具,可以讓切圖變得簡單,這裡推薦兩款:Cutterman和Cut&Slice me,都是Photoshop下的外掛,輸出支援android、ios和web三種平臺。
使用切圖工具雖然方便了,但還是無法避免一套圖片需要提供多張不同尺寸的圖片,這會加大安裝包的大小。另外,需要對圖片做改動時,比如換個顏色,必須更換所有尺寸圖片。所以,建議儘量減少引入圖片,而通過使用shape、layer-list等自己畫,易於修改和維護,也減少了安裝包大小,適配性也更好。

bitmap標籤

可以通過bitmap標籤對圖片做一些設定,如平鋪、拉伸或保持圖片原始大小,也可以指定對齊方式。看看bitmap標籤的一些屬性吧:

  • android:src 必填項,指定圖片資源,只能是圖片,不能是xml定義的drawable資源
  • android:gravity 設定圖片的對齊方式,比如在layer-list中,預設會盡量填滿整個檢視,導致圖片可能會被拉伸,為了避免被拉伸,就可以設定對齊方式,可取值為下面的值,多個取值可以用 | 分隔:
  1. top 圖片放於容器頂部,不改變圖片大小
  2. bottom 圖片放於容器底部,不改變圖片大小
  3. left 圖片放於容器左邊,不改變圖片大小
  4. right 圖片放於容器右邊,不改變圖片大小
  5. center 圖片放於容器中心位置,包括水平和垂直方向,不改變圖片大小
  6. fill 拉伸整張圖片以填滿容器的整個高度和寬度,預設值
  7. center_vertical 圖片放於容器垂直方向的中心位置,不改變圖片大小
  8. center_horizontal 圖片放於容器水平方向的中心位置,不改變圖片大小
  9. fill_vertical 在垂直方向上拉伸圖片以填滿容器的整個高度
  10. fill_horizontal 在水平方向上拉伸圖片以填滿容器的整個寬度
  11. clip_vertical 附加選項,裁剪基於垂直方向的gravity設定,設定top時會裁剪底部,設定bottom時會裁剪頂部,其他情況會同時裁剪頂部和底部
  12. clip_horizontal 附加選項,裁剪基於水平方向的gravity設定,設定left時會裁剪右側,設定right時會裁剪左側,其他情況會同時裁剪左右兩側
  • android:antialias 設定是否開啟抗鋸齒
  • android:dither 設定是否抖動,圖片與螢幕的畫素配置不同時會用到,比如圖片是ARGB 8888的,而螢幕是RGB565
  • android:filter 設定是否允許對圖片進行濾波,對圖片進行收縮或者延展使用濾波可以獲得平滑的外觀效果
  • android:tint 給圖片著色,比如圖片本來是黑色的,著色後可以變成白色
  • android:tileMode 設定圖片平鋪的方式,取值為下面四種之一:
  1. disable 不做任何平鋪,預設設定
  2. repeat 圖片重複鋪滿
  3. mirror 使用交替映象的方式重複圖片的繪製
  4. clamp 複製圖片邊緣的顏色來填充容器剩下的空白部分,比如引入的圖片如果是白色的邊緣,那麼圖片所在的容器裡除了圖片,剩下的空間都會被填充成白色
  • android:alpha 設定圖片的透明度,取值範圍為0.0~1.0之間,0.0為全透明,1.0為全不透明,API Level最低要求是11,即Android 3.0
  • android:mipMap 設定是否可以使用mipmap,但API Level最低要求是17,即Android 4.2
  • android:autoMirrored 設定圖片是否需要映象反轉,當佈局方向是RTL,即從右到左佈局時才有用,API Level 19(Android 4.4)才新增的屬性
  • android:tileModeX 和tileMode一樣設定圖片的平鋪方式,只是這個屬性只設定水平方向的平鋪方式,這是API Level 21(Android 5.0)才新增的屬性
  • android:tileModeY 和tileMode一樣設定圖片的平鋪方式,只是這個屬性只設定垂直方向的平鋪方式,這是API Level 21(Android 5.0)才新增的屬性
  • android:tintMode 著色模式,也是API Level 21(Android 5.0)才新增的屬性

點九圖片

點九圖片副檔名為:.9.png,通過點九圖片可以做區域性拉伸,比如,一張圓角矩形圖片,我們不想讓它的四個邊角都被拉伸從而導致模糊失真,使用點九圖就可以控制拉伸區域,讓四個邊角保持完美顯示。效果如下圖:

畫點九圖一般用Android SDK工具集裡的draw9patch工具,只需要在四條邊畫黑線就可以了,如下圖所示:

拉伸區域就是圖片會被拉伸的部分,可以為1個點,也可以為一條線,甚至也可以為斷開的幾個點或幾條線,總之,有黑點的地方就會被拉伸,沒有黑點的地方就不會被拉伸。而顯示內容區域其實就等於預設給使用的控制元件設定了padding,控制元件的內容只能顯示在內容區域內。

nine-patch標籤

使用nine-patch標籤可以對點九圖片做一些設定處理,不過可設定的屬性並不多:

  • android:src 必填項,必須指定點九型別的圖片
  • android:dither 設定是否抖動,圖片與螢幕的畫素配置不同時會用到,比如圖片是ARGB 8888的,而螢幕是RGB565
  • android:tint 給圖片著色,比如圖片本來是黑色的,著色後可以變成白色
  • android:tintMode 著色模式,API Level 21(Android 5.0)才新增的屬性
  • android:alpha 設定圖片的透明度,取值範圍為0.0~1.0之間,0.0為全透明,1.0為全不透明,API Level最低要求是11
  • android:autoMirrored 設定圖片是否需要映象反轉,當佈局方向是RTL,即從右到左佈局時才有用,API Level 19(Android 4.4)才新增的屬性

color標籤

color標籤是drawable裡最簡單的標籤了,只有一個屬性:android:color,指定顏色值。這個標籤一般很少用,因為基本都可以通過其他更方便的方式定義顏色。另外,顏色值一般都在colors.xml檔案中定義,其根節點為resources。看看兩者的不同:

引用的時候,前一種通過@drawable/white引用,後一種通過@color/white引用。

inset標籤

使用inset標籤可以對drawable設定邊距,其用法和View的padding類似,只不過padding是設定內容與邊界的距離,而inset則可以設定背景drawable與View邊界的距離。inset標籤的可設定屬性如下:

  • android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable型別的子標籤
  • android:visible 設定初始的可見性狀態,預設為false
  • android:insetLeft 左邊距
  • android:insetRight 右邊距
  • android:insetTop 頂部邊距
  • android:insetBottom 底部邊距
  • android:inset 設定統一邊距,會覆蓋上面四個屬性,但API Level要求為21,即Android 5.0

clip標籤

使用clip標籤可以對drawable進行裁剪,在做進度條時很有用。通過設定level值控制裁剪多少,level取值範圍為0~10000,預設為0,表示完全裁剪,圖片將不可見;10000則完全不裁剪,可見完整圖片。看看clip標籤可以設定的屬性:

  • android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable型別的子標籤
  • android:clipOrientation 設定裁剪的方向,取值為以下兩個值之一:
  1. horizontal 在水平方向上進行裁剪,條狀的進度條就是水平方向的裁剪
  2. vertical 在垂直方向上進行裁剪
  • android:gravity 設定裁剪的位置,可取值如下,多個取值用 | 分隔:
    1. top 圖片放於容器頂部,不改變圖片大小。當裁剪方向為vertical時,會裁掉圖片底部
    2. bottom 圖片放於容器底部,不改變圖片大小。當裁剪方向為vertical時,會裁掉圖片頂部
    3. left 圖片放於容器左邊,不改變圖片大小,預設值。當裁剪方向為horizontal,會裁掉圖片右邊部分
    4. right 圖片放於容器右邊,不改變圖片大小。當裁剪方向為horizontal,會裁掉圖片左邊部分
    5. center 圖片放於容器中心位置,包括水平和垂直方向,不改變圖片大小。當裁剪方向為horizontal時,會裁掉圖片左右部分;當裁剪方向為vertical時,會裁掉圖片上下部分
    6. fill 拉伸整張圖片以填滿容器的整個高度和寬度。這時候圖片不會被裁剪,除非level設為了0,此時圖片不可見
    7. center_vertical 圖片放於容器垂直方向的中心位置,不改變圖片大小。裁剪和center時一樣
    8. center_horizontal 圖片放於容器水平方向的中心位置,不改變圖片大小。裁剪和center時一樣
    9. fill_vertical 在垂直方向上拉伸圖片以填滿容器的整個高度。當裁剪方向為vertical時,圖片不會被裁剪,除非level設為了0,此時圖片不可見
    10. fill_horizontal 在水平方向上拉伸圖片以填滿容器的整個寬度。當裁剪方向為horizontal時,圖片不會被裁剪,除非level設為了0,此時圖片不可見
    11. clip_vertical 附加選項,裁剪基於垂直方向的gravity設定,設定top時會裁剪底部,設定bottom時會裁剪頂部,其他情況會同時裁剪頂部和底部
    12. clip_horizontal 附加選項,裁剪基於水平方向的gravity設定,設定left時會裁剪右側,設定right時會裁剪左側,其他情況會同時裁剪左右兩側

那怎麼設定level呢?android沒有提供直接在xml裡設定level的屬性,這需要通過程式碼去設定。舉例用法如下:

  1. 定義clip.xml:
  2. 在ImageView中引用:
  3. 在程式碼中設定level:

scale標籤

使用scale標籤可以對drawable進行縮放操作,和clip一樣是通過設定level來控制縮放的比例。scale標籤可以設定的屬性如下:

  • android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable型別的子標籤
  • android:scaleHeight 設定可縮放的高度,用百分比表示,格式為XX%,0%表示不做任何縮放,50%表示只能縮放一半
  • android:scaleWidth 設定可縮放的寬度,用百分比表示,格式為XX%,0%表示不做任何縮放,50%表示只能縮放一半
  • android:scaleGravity 設定drawable縮放後的位置,取值和bitmap標籤的一樣,就不一一列舉說明了,不過預設值是left
  • android:useIntrinsicSizeAsMinimum 設定drawable原有尺寸作為最小尺寸,設為true時,縮放基本無效,API Level最低要求為11

使用的時候,和clip一樣,用法如下:

  1. 定義scale.xml:
  2. 在ImageView中引用:
  3. 在程式碼中設定level:

level-list標籤

當需要在一個View中顯示不同圖片的時候,比如手機剩餘電量不同時顯示的圖片不同,level-list就可以派上用場了。level-list可以管理一組drawable,每個drawable設定一組level範圍,最終會根據level值選取對應的drawable繪製出來。level-list通過新增item子標籤來新增相應的drawable,其下的item只有三個屬性:

  • android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable型別的子標籤
  • android:minLevel 該item的最小level值
  • android:maxLevel 該item的最大level值

以下是示例程式碼:

那麼,當電量剩下10%時則可以設定level值為10,將會匹配第一張圖片:

item的匹配規則是從上到下的,當設定的level值與前面的item的level範圍匹配,則採用。一般item的新增按maxLevel從小到大排序下來,此時minLevel可以不用指定也能匹配到。如上面程式碼就可以簡化如下:

但不能反過來將android:maxLevel=”100″的item放在最前面,那樣所有電量都只匹配第一條了。

transition標籤

transition其實是繼承自layer-list的,只是,transition只能管理兩層drawable,另外提供了兩層drawable之間切換的方法,切換時還會有淡入淡出的動畫效果。示例程式碼如下:

transition標籤生成的Drawable對應的類為TransitionDrawable,要切換時,需要主動呼叫TransitionDrawable的startTransition()方法,引數為動畫的毫秒數,也可以呼叫reverseTransition()方法逆向切換。

rotate標籤

使用rotate標籤可以對一個drawable進行旋轉操作,在shape篇講環形時最後舉了個進度條時就用到了rotate標籤。另外,比如你有一張箭頭向上的圖片,但你還需要一個箭頭向下的圖片,這時就可以使用rotate將向上的箭頭旋轉變成一張箭頭向下的drawable。
先看看rotate標籤的一些屬性吧:

  • android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable型別的子標籤
  • android:fromDegrees 起始的角度度數
  • android:toDegrees 結束的角度度數,正數表示順時針,負數表示逆時針
  • android:pivotX 旋轉中心的X座標,浮點數或是百分比。浮點數表示相對於drawable的左邊緣距離單位為px,如5; 百分比表示相對於drawable的左邊緣距離按百分比計算,如5%; 另一種百分比表示相對於父容器的左邊緣,如5%p; 一般設定為50%表示在drawable中心
  • android:pivotY 旋轉中心的Y座標
  • android:visible 設定初始的可見性狀態,預設為false

示例程式碼如下,目標是將一張箭頭向上的圖片轉180度,轉成一張箭頭向下的圖片:

將它引用到ImageView裡,發現圖片根本沒有轉變。其實,要讓它可以旋轉,還需要設定level值。level取值範圍為0~10000,應用到rotate,則與fromDegrees~toDegrees相對應,如上面例子的角度範圍為0~180,那麼,level取值0時,則旋轉為0度;level為10000時,則旋轉180度;level為5000時,則旋轉90度。因為level預設值為0,所以圖片沒有轉變。那麼,我們想轉180度,其實可以將fromDegrees設為180,而不設定toDegrees,這樣,不用再在程式碼裡設定level圖片就可以旋轉180了。

animation-list標籤

通過animation-list可以將一系列drawable構建成幀動畫,就是將一個個drawable,一幀一幀的播放。通過新增item子標籤設定每一幀使用的drawable資源,以及每一幀持續的時間。示例程式碼如下:

android:oneshot屬性設定是否迴圈播放,設為true時,只播放一輪就結束,設為false時,則會輪詢播放。
android:duration屬性設定該幀持續的時間,以毫秒數為單位。
animation-list對應的Drawable類為AnimationDrawable,要讓動畫執行起來,需要主動呼叫AnimationDrawable的start()方法。另外,如果在Activity的onCreate()方法裡直接呼叫start()方法會沒有效果,因為view還沒有初始化完成是播放不了動畫的。

animated-rotate

rotate標籤只是將原有的drawable轉個角度變成另一個drawable,它是靜態的。而animated-rotate則會讓drawable不停地做旋轉動畫。
animated-rotate可設定的屬性只有四個:

  • android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable型別的子標籤
  • android:pivotX 旋轉中心的X座標
  • android:pivotY 旋轉中心的Y座標
  • android:visible 設定初始的可見性狀態,預設為false

示例程式碼:


寫在最後

至此,drawable資源基本都講完了,但還不是全部,Android 5.0新增的幾個標籤:animated-selector、vector、animated-vector、ripple,因為還沒弄清楚具體的用法,而且也涉及到Material Design,所以不在本篇講解,後續做Material Design專題分享的時候會再詳細講解用法。
PS:selector標籤下的item其實還可以新增set標籤,這是新增動畫集的標籤,下一篇就將分享下一些常用動畫的製作。

相關文章