Android XML shape 標籤使用詳解
一個android開發者肯定懂得使用 xml 定義一個 Drawable,比如定義一個 rect 或者 circle 作為一個 View 的背景。但是,也肯定也有人在能使用 Drawable 的地方選擇使用一張 png 圖(或者是一張 .9 圖)作為 View 的背景,因為後者把問題交給 UI 設計人員去了,省事。當然,使用圖片這種在專案中也很常見,如果不考慮 apk 大小,記憶體佔用問題的話,是沒有任何問題的。如果要給 apk 瘦身,減少記憶體佔用,那麼本文 Drawable 的價值就提現出來了。首先提出幾個問題?
備註:本文所說的 Drawable 都特指 shape 標籤定義的 Drawable
- shape 標籤定義的 Drawable 是哪種型別的 Drawable?
- 使用 Drawable 有什麼好處?
- 什麼情況下選擇使用 Drawable,而不是使用一張圖,反之呢?
- shape 標籤能定義多少種類型的 Drawable?(這是本文的重點,方便我這種懶惰的程式設計師直接拷貝程式碼修改)
本文需要先了解shape標籤的基本用法,關於Android shape標籤的各個屬性詳解請移步:
首先給出GitHub地址,後續有新的內容會持續加入 https://github.com/PopFisher/AndroidDrawClassic
下面依次回答上面幾個問題
shape標籤定義的Drawable是哪種型別的Drawable?
shape 標籤定義的 Drawable 型別對應 GradientDrawable
這裡可能會認為是 ShapeDrawale ,我一開始也是這樣認為的,因為我看到官方文件上說 ShapeDrawable 也是使用 shape 標籤定義的,可是去看 GradientDrawable 的時候也是同樣的解釋,簡直懵逼了,後面經過程式碼實際檢驗,shape 標籤定義的 Drawable 能直接強制轉換為 GradientDrawable,而不能轉換為 ShapeDrawable,這個時候只能認為是 ShapeDrawable 的文件解釋有點問題了,可能文件錯了吧。
ShapeDrawable 與 GradientDrawale 確實有很多相似之處,具體情況後續單獨寫文章來說明,本文不涉及 ShapeDrawable 的其他內容。
使用Drawable有什麼好處?
- 很方便得到一個矩形,圓,橢圓,圓環,很容易維護和修改
- 很方便實現圓角,漸變(線性漸變,徑向漸變,掃描漸變)
- 代替圖片作為 View 的背景,減少 apk 的體積(減少 apk 體積最明顯最有效的步驟就是去掉圖片)
- 大圖片耗記憶體,使用 Drawable 節省記憶體,Android 本身對 Drawable 做了很好的優化(記憶體優化需要考慮)
什麼情況下選擇使用Drawable,而不是使用一張圖,反之呢?
- 理論上能用 Drawable 的地方就用 Drawable
- 如果能夠通過 shape 標籤就能定義的幾何圖形就能滿足需求,就不用圖片來表示
- 漸變型別的背景也儘量使用 shape 來實現
- 不規則的,複雜的圖形還是隻能使用圖片,比如要一個表示手機的圖示,一個人的頭像
- 有些特殊拉昇效果需要使用 .9.png 圖片(儘可能的小吧,越小越省記憶體)
shape標籤能定義多少種類型的Drawable?
shape 可以定義四種類型的幾何圖形,由 android:shape 屬性指定
line --> 線
rectangle --> 矩形(圓角矩形)
oval --> 橢圓,圓
ring --> 圓環
shape 可以定義邊框屬性
有邊框,無邊框,虛線邊框,實線邊框
shape 可以實現矩形圓角效果
可以指定其中一個角或者多個角設定圓角效果
指定圓角半徑設定圓角的大小
shape 可以實現三種漸變,由子標籤 gradient 實現
linear --> 線性漸變(水平,垂直,對角線三個漸變)
sweep --> 掃描漸變(只支援順時針方向,其實顏色反過來就跟逆時針一樣的了)
radial --> 徑向漸變(由指定的中心點開始向外漸變,指定半徑)
xml 實現只支援三個顏色,startColor,CenterColor,endColor
由上面的組合可以定義很多 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怎麼通過程式碼的方式建立並使用?