一個android開發者確定懂得使用 xml 定義一個 Drawable,好比定義一個 rect 或者 circle 做爲一個 View 的背景。可是,也確定也有人在能使用 Drawable 的地方選擇使用一張 png 圖(或者是一張 .9 圖)做爲 View 的背景,由於後者把問題交給 UI 設計人員去了,省事。固然,使用圖片這種在項目中也很常見,若是不考慮 apk 大小,內存佔用問題的話,是沒有任何問題的。若是要給 apk 瘦身,減小內存佔用,那麼本文 Drawable 的價值就提現出來了。首先提出幾個問題?html
備註:本文所說的 Drawable 都特指 shape 標籤訂義的 Drawableandroid
本文須要先了解shape標籤的基本用法,關於Android shape標籤的各個屬性詳解請移步:git
Android GradientDrawable(shape標籤訂義) 靜態使用和動態使用(圓角,漸變實現)程序員
首先給出GitHub地址,後續有新的內容會持續加入
Github地址:https://github.com/PopFisher/AndroidDrawClassicgithub
下面依次回答上面幾個問題佈局
shape 標籤訂義的 Drawable 類型對應 GradientDrawable學習
這裏可能會認爲是 ShapeDrawale ,我一開始也是這樣認爲的,由於我看到官方文檔上說 ShapeDrawable 也是使用 shape 標籤訂義的,但是去看 GradientDrawable 的時候也是一樣的解釋,簡直懵逼了,後面通過代碼實際檢驗,shape 標籤訂義的 Drawable 能直接強制轉換爲 GradientDrawable,而不能轉換爲 ShapeDrawable,這個時候只能認爲是 ShapeDrawable 的文檔解釋有點問題了,可能文檔錯了吧。優化
ShapeDrawable 與 GradientDrawale 確實有不少類似之處,具體狀況後續單獨寫文章來講明,本文不涉及 ShapeDrawable 的其餘內容。設計
shape 能夠定義四種類型的幾何圖形,由 android:shape 屬性指定3d
line --> 線
rectangle --> 矩形(圓角矩形)
oval --> 橢圓,圓
ring --> 圓環
shape 能夠定義邊框屬性
有邊框,無邊框,虛線邊框,實線邊框
shape 能夠實現矩形圓角效果
能夠指定其中一個角或者多個角設置圓角效果
指定圓角半徑設置圓角的大小
shape 能夠實現三種漸變,由子標籤 gradient 實現
linear --> 線性漸變(水平,垂直,對角線三個漸變)
sweep --> 掃描漸變(只支持順時針方向,其實顏色反過來就跟逆時針同樣的了)
radial --> 徑向漸變(由指定的中心點開始向外漸變,指定半徑)
xml 實現只支持三個顏色,startColor,CenterColor,endColor
更多更詳細關於 shape 的介紹請移步 Android GradientDrawable(shape標籤訂義) 靜態使用和動態使用(圓角,漸變實現)
由上面的組合能夠定義不少 Drawable,下面依次進行介紹:
實線:line_solid.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 實線 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" /> </shape>
虛線:line_dashed.xml
<?xml version="1.0" encoding="utf-8"?> <!--虛線 設置類型會line 須要關閉硬件加速虛線才能繪製出來,佈局文件中使用的時候須要設置android:layerType="software" android:width 線寬,佈局文件中的View的高度須要比這個值大才能夠繪製出來 android:dashWidth 每段破折線的長度 android:dashGap="5dp"每段破折線之間的間隔--> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="line" android:useLevel="true"> <stroke android:width="2dp" android:dashGap="5dp" android:dashWidth="10dp" android:color="#ffff0000" /> </shape>
矩形實線邊框內部無填充:rect_solid_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 實線邊框 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" /> </shape>
矩形虛線邊框內部無填充:rect_dashed_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 虛線邊框 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" android:dashGap="5dp" android:dashWidth="10dp" /> </shape>
矩形實線邊框-內部填充:rect_solid_border_and_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 實線邊框+內部填充 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" /> <solid android:color="#ff00ffff" /> </shape>
矩形虛線邊框-內部填充:rect_dashed_border_and_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 虛線邊框+內部填充 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" android:dashGap="5dp" android:dashWidth="10dp" /> <solid android:color="#ff00ffff" /> </shape>
圓角矩形-只有邊框:rect_rounded_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形邊框圓角 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:height="100dp" android:width="100dp"/> <stroke android:width="2dp" android:color="#ffff0000" /> <corners android:bottomLeftRadius="2dp" android:bottomRightRadius="2dp" android:topLeftRadius="2dp" android:topRightRadius="2dp" /> </shape>
圓角矩形-只有內部填充:rect_rounded_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓角矩形 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:height="100dp" android:width="100dp"/> <solid android:color="#8000ff00" /> <corners android:bottomLeftRadius="2dp" android:bottomRightRadius="2dp" android:topLeftRadius="2dp" android:topRightRadius="2dp" /> </shape>
圓角矩形-有邊框有填充:rect_rounded_border_and_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形邊框+填充 圓角 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:height="100dp" android:width="100dp"/> <stroke android:width="2dp" android:color="#ffff0000" /> <solid android:color="#8000ff00" /> <corners android:bottomLeftRadius="2dp" android:bottomRightRadius="2dp" android:topLeftRadius="2dp" android:topRightRadius="2dp" /> </shape>
圓角矩形-左邊圓角爲一個半圓弧:rect_rounded_left_arc.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形圓角+左右兩邊爲一個圓弧 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="50dp" android:height="10dp" /> <solid android:color="#8000ff00" /> <!-- 圓角半徑是高度的通常就是一個圓弧了 --> <corners android:bottomLeftRadius="20dp" android:topLeftRadius="20dp" /> </shape>
圓角矩形-左右兩邊都是半圓弧:rect_rounded_left_right_arc.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形圓角+左右兩邊爲一個圓弧 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="50dp" android:height="10dp" /> <solid android:color="#8000ff00" /> <!-- 圓角半徑是高度的通常就是一個圓弧了 --> <corners android:radius="20dp" /> </shape>
圓角矩形-左右兩邊都是半圓弧-帶邊框:rect_rounded_left_right_arc_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形圓角+左右兩邊爲一個圓弧 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="50dp" android:height="10dp" /> <stroke android:color="#ffff0000" android:width="2dp"/> <solid android:color="#8000ff00" /> <!-- 圓角半徑是高度的通常就是一個圓弧了 --> <corners android:radius="20dp" /> </shape>
圓角矩形-圓:rect_rounded_arc.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形圓角+圓出一個圓弧 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:height="10dp" android:width="10dp"/> <solid android:color="#8000ff00" /> <corners android:radius="20dp" /> </shape>
圓角矩形-上下兩邊半圓弧:rect_rounded_top_bottom_arc.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形圓角+左右兩邊爲一個圓弧 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="10dp" android:height="60dp" /> <solid android:color="#8000ff00" /> <!-- 圓角半徑是高度的通常就是一個圓弧了 --> <corners android:radius="10dp" /> </shape>
垂直線性漸變:rect_gradient_linear_vertical.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形內部填充-線性垂直漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="@dimen/shape_size" android:height="@dimen/shape_size" /> <stroke android:width="1px" android:color="#ffff00ff" /> <!-- 調整angle實現水平漸變,垂直漸變或者對角漸變 --> <gradient android:angle="-45" android:centerX="0.5" android:centerY="0.4" android:centerColor="#8000ff00" android:endColor="#1000ff00" android:startColor="#ff00ff00" android:type="linear" /> </shape>
水平線性漸變:rect_gradient_linear_horizon.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形內部填充-線性水平漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="@dimen/shape_size" android:height="@dimen/shape_size" /> <stroke android:width="1px" android:color="#ffff00ff" /> <!-- 調整angle實現水平漸變,垂直漸變或者對角漸變 --> <gradient android:angle="0" android:centerX="0.5" android:centerY="0.5" android:centerColor="#8000ff00" android:endColor="#ff00ff00" android:startColor="#1000ff00" android:type="linear" /> </shape>
對角線線性漸變:rect_gradient_linear_diagonal.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形內部填充-線性對角線漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="@dimen/shape_size" android:height="@dimen/shape_size" /> <stroke android:width="1px" android:color="#ffff00ff" /> <!-- 調整angle實現水平漸變,垂直漸變或者對角漸變 --> <gradient android:angle="45" android:centerX="0.5" android:centerY="0.5" android:centerColor="#8000ff00" android:endColor="#1000ff00" android:startColor="#ff00ff00" android:type="linear" /> </shape>
徑向漸變:rect_gradient_radial.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形內部填充-徑向漸變,通常不用在rect上,用到圓或者橢圓上 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <size android:width="@dimen/shape_size" android:height="@dimen/shape_size" /> <stroke android:width="1px" android:color="#ffff00ff" /> <!-- 徑向漸變angle無效 --> <gradient android:angle="0" android:centerX="0.5" android:centerY="0.5" android:startColor="#0000ff00" android:endColor="#ff00ff00" android:gradientRadius="40dp" android:type="radial" /> </shape>
掃描漸變:rect_gradient_sweep.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 矩形內部填充-掃描漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:useLevel="true"> <!--若是佈局中沒有設置View的大小,會size設置的大小爲默認值--> <size android:width="20dp" android:height="20dp" /> <stroke android:width="1px" android:color="#ffff00ff" /> <!--調整angle不能實現角度變化 centerX,centerY是中心點的位置,這裏用的是百分比值(0-1) 在rect中gradientRadius無效--> <gradient android:angle="0" android:centerX="0.5" android:centerY="0.5" android:startColor="#ff00ff00" android:gradientRadius="20dp" android:type="sweep" /> </shape>
圓-邊框:circle_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓形邊框 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <size android:width="80dp" android:height="80dp" /> <stroke android:width="2dp" android:color="#ffff0000" /> </shape>
圓-填充:circle_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓形邊框 + 填充 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <size android:width="80dp" android:height="80dp" /> <solid android:color="#800000ff" /> </shape>
圓-邊框填充:circle_border_and_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓形邊框 + 填充 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <size android:width="80dp" android:height="80dp" /> <stroke android:width="2dp" android:color="#ffff0000" /> <solid android:color="#800000ff" /> </shape>
線性漸變:circle_gradient_linear.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓形內部填充-線性漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <size android:width="@dimen/shape_size" android:height="@dimen/shape_size" /> <!-- angle調整漸變角度,只能是45的倍數,centerX, centerY是百分百(0-1) --> <gradient android:angle="-90" android:centerX="0.5" android:centerY="0.8" android:centerColor="#80ff0000" android:endColor="#ffff0000" android:startColor="#00ff0000" android:type="linear" /> </shape>
徑向漸變:circle_gradient_radial.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓形內部填充-徑向漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <size android:width="40dp" android:height="40dp" /> <!-- centerX, centerY是百分百(0-1) --> <gradient android:centerX="0.5" android:centerY="0.5" android:startColor="#ffff0000" android:centerColor="#80ff0000" android:endColor="#10ff0000" android:gradientRadius="30dp" android:type="radial" /> </shape>
掃描漸變:circle_gradient_sweep.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓形內部填充-掃描漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <size android:width="@dimen/shape_size" android:height="@dimen/shape_size" /> <!-- sweep類型angle,gradientRadius無效,centerX, centerY是百分百(0-1) --> <gradient android:centerX="0.5" android:centerY="0.6" android:startColor="#ffff0000" android:centerColor="#80ff0000" android:endColor="#20ff0000" android:gradientRadius="20dp" android:type="sweep" /> </shape>
邊框:oval_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 橢圓邊框 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" /> </shape>
填充:oval_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 橢圓填充--> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <solid android:color="#800000ff" /> </shape>
邊框+填充:oval_border_and_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 橢圓邊框 + 填充--> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true"> <stroke android:width="2dp" android:color="#ffff0000" /> <solid android:color="#800000ff" /> </shape>
線性漸變:oval_gradient_linear.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 橢圓內部填充-線性漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true" > <size android:width="80dp" android:height="60dp" /> <gradient android:angle="45" android:centerX="0.5" android:centerY="0.7" android:centerColor="#80ff0000" android:endColor="#ffff0000" android:startColor="#00ff0000" android:type="linear" /> </shape>
徑向漸變:oval_gradient_radial.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 橢圓內部填充-徑向漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true" > <size android:width="80dp" android:height="60dp" /> <gradient android:centerX="0.5" android:centerY="0.5" android:centerColor="#80ff0000" android:endColor="#00ff0000" android:startColor="#ffff0000" android:gradientRadius="40dp" android:type="radial" /> </shape>
掃描漸變:oval_gradient_sweep.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 橢圓內部填充-掃描漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" android:useLevel="true" > <size android:width="80dp" android:height="60dp" /> <gradient android:centerX="0.5" android:centerY="0.5" android:centerColor="#80ff0000" android:endColor="#ffff0000" android:startColor="#00ff0000" android:type="sweep" /> </shape>
環內填充:ring_fill.xml
<?xml version="1.0" encoding="utf-8"?><!-- 圓環 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadiusRatio="4" android:shape="ring" android:thicknessRatio="4" android:useLevel="false"> <!--android:useLevel="false"必須是false--> <size android:width="80dp" android:height="80dp" /> <solid android:color="#80ff0000" /> </shape>
圓環邊框:ring_border.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓環-僅有邊框 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadius="20dp" android:shape="ring" android:thickness="16dp" android:useLevel="false"> <!--android:useLevel="false"必須是false--> <size android:width="80dp" android:height="80dp" /> <stroke android:width="2dp" android:color="#ffff00ff" /> </shape>
邊框+填充:ring_border_and_fill.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓環 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:innerRadius="20dp" android:shape="ring" android:thickness="16dp" android:useLevel="false"> <!--android:useLevel="false"必須是false--> <size android:width="80dp" android:height="80dp" /> <solid android:color="#80ff0000" /> <stroke android:width="2dp" android:color="#ffff00ff" /> </shape>
線性漸變:ring_gradient_linear.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓環-線性漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring" android:innerRadius="10dp" android:thickness="30dp" android:useLevel="false"> <!--android:useLevel="false"必須是false--> <size android:width="80dp" android:height="80dp" /> <gradient android:angle="45" android:centerColor="#80ff0000" android:endColor="#ffff0000" android:startColor="#00ff0000" android:type="linear" /> </shape>
徑向漸變:ring_gradient_radial.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓環-徑向漸變漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring" android:innerRadius="10dp" android:thickness="30dp" android:useLevel="false"> <!--android:useLevel="false"必須是false--> <size android:width="80dp" android:height="80dp" /> <!--設置徑向漸變半徑,漸變從圓心開始--> <gradient android:centerX="0.5" android:centerY="0.5" android:centerColor="#80ff0000" android:endColor="#00ff0000" android:startColor="#ffff0000" android:gradientRadius="40dp" android:type="radial" /> </shape>
掃描漸變:ring_gradient_sweep.xml
<?xml version="1.0" encoding="utf-8"?> <!-- 圓環-線性漸變 --> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="ring" android:innerRadius="10dp" android:thickness="30dp" android:useLevel="false"> <!--android:useLevel="false"必須是false--> <size android:width="80dp" android:height="80dp" /> <!--掃描漸變shape不能設置角度--> <gradient android:centerColor="#80ff0000" android:endColor="#ffff0000" android:startColor="#00ff0000" android:type="sweep" /> </shape>
熟練掌握好 shape 標籤的使用,可以構建出多種多樣的 Drawable,這些 Drawable 能夠直接做爲背景設置給 View,代碼經過 R.drawable 方式使用,xml 文件經過 @drawable/name 使用。跟圖片的使用如出一轍,關鍵是使用系統 Drawable 能夠減小 apk 的體積,減小內存佔用等好處,因此,不要以爲簡單就不繫統學習,越簡單的東西越要熟練掌握。後面還會陸續出一些 Drawable 的文章,好比除了shape標籤訂義的 Drawable,其餘還有哪些 xml 標籤能定義 Drawable? Drawable怎麼經過代碼的方式建立並使用?