今天為了適配啟動頁背景圖,接觸到了BitmapDrawable保證了時的背景圖不變形。想想之前真的沒用過,所以還是有必要詳細瞭解一下Drawable,至少在遇到一些問題時可以及時的找到解決方案。
Drawable的分類
Drawable一般都是用XML定義的,但是我們也可以自定義Drawable,但是程式碼會比較複雜。
BitmapDrawablw
可以理解為它是一張帶規則的圖片,一般情況下如果可以在ImageView裡面設定屬性的就沒必要使用,但是如果一張圖片要做到像放在控制元件裡適配就有必要使用了,例如啟動頁背景圖
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="clip_horizontal|clip_vertical"
android:dither="true"
android:src="@drawable/splash_bg"
android:tileMode="disabled"/>
<!--屬性解釋-->
<!--android:src 圖片資源id-->
<!--android:antialias是否開啟抗鋸齒,應該開啟-->
<!--android:dither是否開啟抖動效果,應該開啟-->
<!--android:filter是否開啟過濾效果,應該開啟-->
<!--android:gravity對圖片進行定位-->
<!--android:mipMap紋理對映,一般為false-->
<!--android:tileMode平鋪模式四個值:disabled(預設值即關閉平鋪模式)、clamp、repeat、mirror-->
複製程式碼
如果直接使用圖片,由於不能控制圖片的位置,有些手機會變形很嚴重。
NinePatchDrawable
與BitmapDrawable類似不過NinePatchDrawable的效果類似於.9圖,實際使用時其實直接使用.9圖就好
ShapeDrawable
開發時用的比較多,可以理解為只有純顏色或漸變色的圖片。只是有些地方需要注意一下。
以上程式碼是一個指定漸變百分比的漸變shape,其中centerY與centerColor必須同時設定才能生效,否則只是普通的漸變,另外,其實我們的系統進度條也可以設定漸變
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:max="1000"
android:progress="0"
android:progressDrawable="@drawable/progress_green" />
複製程式碼
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="3dp"
android:max="1000"
android:progress="0"
android:progressDrawable="@drawable/progress_green" />
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_green-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="50dp" />
<solid android:color="@android:color/transparent" />
</shape>
</item>
<item android:id="@android:id/progress">
<scale
android:drawable="@drawable/progress_shape"
android:scaleWidth="100%" />
</item>
</layer-list>
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_shape-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="@color/theme_color"
android:startColor="@color/theme_color1"
android:type="linear" />
</shape>
複製程式碼
進度條max的值由於沒有小數,所以設定1000效果會好很多,加上動畫效果後效果如下
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!--<solid android:color="#F4D78C" />-->
<gradient
android:angle="90"
android:centerY="0.7"
android:endColor="@color/green_00A9BA"
android:centerColor="@color/theme_color1"
android:startColor="@color/theme_color1"></gradient>
</shape>
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_green-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
<shape>
<corners android:radius="50dp" />
<solid android:color="@android:color/transparent" />
</shape>
</item>
<item android:id="@android:id/progress">
<scale
android:drawable="@drawable/progress_shape"
android:scaleWidth="100%" />
</item>
</layer-list>
複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<!--progress_shape-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="0"
android:endColor="@color/theme_color"
android:startColor="@color/theme_color1"
android:type="linear" />
</shape>
複製程式碼
進度條max的值由於沒有小數,所以設定1000效果會好很多,加上動畫效果後效果如下
LayerDrawable
對應的標籤是layer-list,表示一種層次化的Drawable。很多時候都可以使用佈局巢狀完成,但是使用layor-list可以減少佈局的層級結構,例如
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<stroke android:width="1dp" android:color="#45DAA8" />
</shape>
</item>
<item>
<bitmap android:src="@drawable/gou"
android:gravity="bottom|right" />
</item>
</layer-list>
複製程式碼
效果圖
StateListDrawble
這個開發中也經常用到,標籤對應的是selector。比如我們的點選效果、還有選擇後與選擇前的不同效果,使用selector可以在程式碼中設定一個屬性改變很方便。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/bg_btn_circle_gradient_full">
</item>
<item android:state_enabled="false">
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#aaffffff">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:radius="360dp" />
<solid
android:color="@color/gray_eeeeee"
/>
</shape>
</item>
</ripple>
</item>
</selector>
複製程式碼
這裡結合了ripple標籤,可以做出水波紋效果。效果如下
LevelListDrawable
也是一個Drawable的集合,對應的標籤是level-list。有點類似於layer-list,不過level-list是根據等級(0~10000)來顯示的,而layer-list則是顯示在一起的。開發中比較少用到,如果一個按鈕有多種狀態可以考慮使用代替if-else判斷顯示
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/icon_heat" android:maxLevel="1"/>
<item android:drawable="@drawable/icon_cool" android:maxLevel="2"/>
</level-list>
複製程式碼
imageview.getDrawable().setLevel(1);
複製程式碼
TransitionDrawable
可以實現兩個Drawable之間的淡入淡出,對應的標籤是transition。
ScaleDrawable
對應的標籤是scale,可以根據level指定Drawable縮放到一定比例。
這兩個效果我覺得可以在啟動頁的背景圖做一點動畫效果或者做全域性的動畫,其他地方可以使用動畫代替。
InsetDrawable
對應的標籤是inset,可以把Drawable內嵌進來,可以用於加大點選區域。
ClipDrawable
對應的標籤是clip,可以根據level裁剪出另外一個drawabl。挺有用的一個Drawable可以看看下面的部落格 效果圖:
自定義Drawable
其實Drawable是一個抽象的概念,可以理解為Canvas之前的一個封裝。就是把資源封裝成Drawable再繪製到畫布上。Drawable可以說是記憶體級的畫布。
過程與自定義View時的繪畫是相似的,具體也上面ClipDrawable的部落格。
參考資料
《Android開發藝術探索》