【Android Drawable系列】- shape xml屬性詳解

Android Drawable系列

日常開發(fā)中,一些簡單的背景或者圖形都會使用xml的shape標簽完成,經(jīng)常使用在按鈕的背景上。

shape的優(yōu)點還是很多的

  • 文件比切圖小
  • 節(jié)約內存
  • 支持拉伸

shape的屬性雖然比較簡單,但是也能繪制出一些比較復雜的形狀

概覽

首先來看看shape標簽所支持的標簽以及屬性,如下圖:

Shape

左側是shape標簽的自身屬性,右側是shape標簽所支持的標簽和標簽的屬性。

下面是一份xml屬性實例和說明

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:dither=["true" | "false"]       //將在位圖的像素配置與屏幕不同時(例如:ARGB 8888 位圖和 RGB 565 屏幕)啟用位圖的抖動;值為“false”時則停用抖動。默認值為 true。
    android:shape=["rectangle" | "oval" | "line" | "ring"]//分別為矩形、橢圓、線、環(huán)。默認為矩形rectangle 
    android:innerRadius="integer"           // shape為ring時有效,內環(huán)半徑
    android:innerRadiusRatio="float"        // shape為ring時有效,內環(huán)的厚度比,即環(huán)的圖形寬度與內環(huán)半徑的比例,按照這個比例計算內環(huán)半徑,默認為3,可被innerRadius值覆蓋
    android:thickness="integer"             // shape為ring時有效,環(huán)的厚度
    android:thicknessRatio="float"          // shape為ring時有效,環(huán)的厚度比,即環(huán)的圖形寬度與環(huán)的厚度的比例,按照這個比例計算環(huán)的厚度,默認為9,可被thickness值覆蓋
    android:tint="color"                    // 給shape著色
    android:tintMode=["src_in" | "src_atop" | "src_over" | "add" | "multiply" | "screen"] // 著色類型
    android:useLevel=["true" | "false"]     // 較少用,一般設為false,否則圖形不顯示。為true時可在LevelListDrawable使用
    android:visible=["true" | "false"] >
    <!-- 圓角 -->
    <corners
        android:radius="integer"            // 圓角半徑,設置下面四個屬性時,對應的位置屬性會被覆蓋
        android:topLeftRadius="integer"     // 左上角圓角半徑
        android:topRightRadius="integer"    // 右上角圓角半徑
        android:bottomLeftRadius="integer"  // 左下角圓角半徑
        android:bottomRightRadius="integer" // 右下角圓角半徑
        />
    <!-- 漸變 -->
    <gradient
        android:type=["linear" | "radial" | "sweep"]// 漸變類型,線性、放射性、掃描性;默認為線性
        android:angle="integer"             // 漸變角度,漸變類型為linear時有效;默認為0,從左至右漸變,角度逆時針方向計算,角度需要時45的整數(shù)倍數(shù)
        android:centerColor="integer"       // 漸變中間位置顏色
        android:startColor="color"          // 漸變開始位置顏色
        android:endColor="color"            // 漸變結束位置顏色
        android:centerX="float"             // 設置漸變中心的X坐標,取值區(qū)間[0,1],默認為0.5,即中心位置
        android:centerY="float"             // 設置漸變中心的Y坐標,取值區(qū)間[0,1],默認為0.5,即中心位置
        android:gradientRadius="integer"    // type為放射性漸變radial時有效,漸變的半徑
        android:useLevel=["true" | "false"] // 與shape中該屬性的一致
        />
    <!-- 內邊距 -->
    <padding
        android:left="integer"              // 左邊距
        android:top="integer"               // 上邊距
        android:right="integer"             // 右邊距
        android:bottom="integer"            // 下邊距
        />
    <!-- 大小 -->
    <size
        android:width="integer"             // 圖形寬度
        android:height="integer"            // 圖形高度
        />
    <!-- 填充 -->
    <solid
        android:color="color"               // 圖形的填充色
        />
    <!-- 描邊 -->
    <stroke
        android:width="integer"             // 描邊的寬度
        android:color="color"               // 描邊的顏色
        android:dashWidth="integer"         // 虛線寬度
        android:dashGap="integer"           // 虛線間隔
        />
</shape>

因為shape中的屬性更的是組合使用,所以舉例沒法單獨只使用一個標簽。

solid、corners和stroke

經(jīng)常使用的就是solidcorners、stroke這三個標簽

下面是這個Button背景的xml代碼

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <corners android:radius="10dp"/>

    <solid android:color="#008577"/>

    <stroke
        android:width="3dp"
        android:color="#D81B60"
        android:dashWidth="10dp"
        android:dashGap="5dp"/>
</shape>

solid就是整個區(qū)域的填充色

corners則是控制了背景的4個角的圓角半徑

stroke控制了描邊的屬性,color表示線的顏色;width描邊的寬度,其實就是圖中紅線的高度;dashWidth表示虛線中紅線的寬度;dashGap表示虛線間隔寬度,也就是紅色之間的間隔距離

corners屬性覆蓋

再來看看corners標簽的屬性覆蓋規(guī)則。下圖中將radius屬性設置為10dp,并同時設置給其他的四個屬性不同的值,從圖中可以看出四個屬性將都radius屬性覆蓋了。

具體的xml代碼:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <corners
        android:bottomLeftRadius="30dp"
        android:bottomRightRadius="40dp"
        android:radius="10dp"
        android:topLeftRadius="0dp"
        android:topRightRadius="20dp"/>

    <solid android:color="#008577"/>
</shape>

padding

再來看看padding標簽的作用,圖片如下:

第一行的TextView的背景沒有設置padding屬性;第二行則是使用了padding標簽,不低的地方在于有無內容的差別。shape的xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#008577"/>
    <padding
        android:bottom="10dp"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp"/>

</shape>

shape中雖然使用了padding標簽,但是在被設置該背景的view上依然可以通過修改paddingLeft等對應的相關屬性進行覆蓋。

size

size控制圖形的寬高尺寸,對應屬性也就android:widthandroid:height

但是,在作為背景的情況下,shape的size屬性并不是完全有效的,最后的顯示效果還是會由view來決定,size只是在view的寬(或高)為wrap_content且顯示內容后的實際大小不超過size所設置的值得時候才會生效。這個效果其實比較類似minWidth
minHeight兩個屬性的效果。

下圖中,左邊的內容沒有超出,按照size所設置的大小顯示,而右邊的內容超出了size所設置的大小,按照實際大小顯示。這里比較簡單,不上代碼了。

不要這樣就覺得size沒有什么作用,例如下圖

截圖的原因,圖片被放大了,這些圓使用ImageViewsrc顯示時,ImageView只需要設置wrap_content就可以按照設置的大小顯示了。

當然,如果你修改了ImageView的大小,那shape的顯示就會根據(jù)ImageViewscaleType來決定最后的顯示效果了。

gradient

不太清楚gradient標簽的使用頻率,畢竟是UI效果,實際工作中涉及到漸變的時候基本都是設計小姐姐直接給圖的。不過不妨礙我們了解gradient的用法。

android:type

這里先說android:type屬性,表示漸變類型,有三個可以選擇的屬性linear線性、radial放射性、sweep掃描性,默認為線性

下圖,從左到右的中android:type分別是linear線性、radial放射性、sweep掃描性

  • 線性:比較好理解,就是一條線從左到右,準確的說是從一邊到另一邊漸變,而這個方向是可以調整的,后面會說明
  • 放射性:從一個中心點向外漸變
  • 掃描性:這個比較像雷達,具體看圖,我描述不出來,不過也是有中心點的
漸變顏色

先以默認漸變類型來看下主要的三個屬性:

  • android:centerColor 漸變中間位置的顏色
  • android:endColor 漸變結束位置的顏色
  • android:startColor 漸變開始位置的顏色

上圖中第一個按鈕,設置了開始顏色是紅的,中間顏色是白色,結束顏色是綠的,具體代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:centerColor="#FFFFFF"
        android:startColor="#D81B60"
        android:endColor="#008577"/>
    <corners android:radius="10dp"/>
</shape>
android:angle

start -> end默認的方向是從左到右,通過設置android:angle屬性可以修改這個方向,0 -> 360 增加時,方向是逆時針調整的。上圖中,第2、3、4個按鈕的shapeandroid:angle屬性值分別是90、180、270。注意,android:angle屬性需要時45的整數(shù)倍。

android:centerX和android:centerY

這兩個屬性是控制漸變中心位置的坐標的,取值區(qū)間[0,1],默認為0.5

上圖中,三種漸變類型都設置了中心點的位置,radialsweep兩種類型比較好理解,就是控制中心在圖形中的的相對位置。

linear類型也會受到這兩個屬性的改變,因為是線性所以作用應該是對線的中心點的控制,我試了一下,centerX或者centerY都能控制漸變的中心點,而且不受android:angle屬性影響。但是centerXcenterY同時使用時,不存在屬性前后順序而導致屬性覆蓋的的情況,只有centerX起作用。

android:gradientRadius

設置漸變的半徑,當type為放射性漸變radial時有效,差異效果如下圖:

solidgradient同時使用時,在代碼中比較靠下的標簽會覆蓋之前的標簽屬性

shape

shape的標簽屬性都了解完了,接著就是shape自身的屬性了

前面舉例的都是矩形,也就是android:shape="rectangle"的情況下,接下來看看其他三種類型,

首先是line,因為虛線和實線相差兩個屬性,就直接用虛線舉例了

下面是具體的xml代碼:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line">
    <stroke
        android:width="3dp"
        android:color="#D81B60"
        android:dashWidth="10dp"
        android:dashGap="5dp"/>
    <size android:height="10dp"/>
</shape>

經(jīng)過查資料和一些測試,使用line類型有些限制

  • 必須使用stroke標簽,view顯示的高度必須大于(必須是大于,等于都不行)stroke標簽中width寬度屬性的值。也就是說,view所設置的高度需要大于虛線高度;如果使用了size標簽,sizeheight也必須比大于虛線高度
  • 4.0 以上手機,默認使用硬解碼,虛線在真機會顯示成實線,可以關閉頁面的硬件加速,也可以給相關的view設置成軟解layerType="software"

再來是oval,雖然表示的是橢圓,其實只需要顯示圖形的view是正方形就可以顯示成圓了。之前在使用size就是以圓為例子舉例的,在ImageViewsrc中使用shape,xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#008577"/>
    <size android:width="20dp"
          android:height="20dp"/>
</shape>

當然,也可以通過限制view的寬高,來保證顯示圓。

ovalrectangle在使用其他的屬性方面規(guī)則基本一直,只是corners標簽不在具有任何效果。

最后是ring,關于ring的屬性比其他的三種圖形要多出4個屬性

  • innerRadius,shape為ring時有效,內環(huán)半徑
  • innerRadiusRatio,shape為ring時有效,內環(huán)的厚度比,即環(huán)的圖形寬度與內環(huán)半徑的比例,按照這個比例計算內環(huán)半徑,默認為3,可被innerRadius值覆蓋
  • thickness,shape為ring時有效,環(huán)的厚度
  • thicknessRatio,shape為ring時有效,環(huán)的厚度比,即環(huán)的圖形寬度與環(huán)的厚度的比例,按照這個比例計算環(huán)的厚度,默認為9,可被thickness值覆蓋

上圖中第一個環(huán)的xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:useLevel="false"
    android:shape="ring">
    <solid android:color="#008577"/>
    <size android:width="100dp"
          android:height="100dp"/>
</shape>

可以看到并沒有設置什么其他的屬性,只是設置了solidsize,這基本就是默認的一個環(huán)了,內環(huán)半徑和環(huán)的厚度都是分別是按3和9的比例計算的,后面會具體講解這兩個值得意思。

第二個環(huán),則是添加android:thickness="5dp"屬性,設置了環(huán)的厚度為5dp

第三個環(huán),則是添加android:innerRadius="10dp"屬性,設置內環(huán)半徑為10dp

第四個環(huán),可以算解釋了innerRadiusRatiothicknessRatio兩個屬性,具體xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:useLevel="false"
    android:innerRadiusRatio="3"
    android:thicknessRatio="100"
    android:shape="ring">
    <solid android:color="#008577"/>
    <size android:width="200dp" android:height="200dp"/>
</shape>

innerRadiusRatiothicknessRatio兩個屬性都是對比view最終顯示的大小來計算的,可以對應著兩個公式:
innerRadius = view.width / innerRadiusRatio
thickness = view.width / thicknessRatio

這樣以來著兩個屬性就比較好理解了

對于ring的使用還有幾點需要注意:

  • 必須寫useLevel="false",否則不顯示
  • 如果android:thicknessandroid:innerRadius設置了值,無論view的大小如何設置,將不會影響圖片大小,這有可能會導致圖形顯示不全。
  • paddingcorners兩個標簽不起作用,其他的標簽可以正常的使用
PS:好了,shape的基本屬性算是了解完了,如有不正確的地方,還請大佬指正。

如果喜歡該文章,可以掃碼領個紅包支持一下

圖片發(fā)自簡書App
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 伊稚斜華美,於單傲嬌,總以為狼群里長大的小玉終究屬于草原,卻不想她一生愛恨糾葛都在精致的長安。 月牙泉邊,她初次遇...
    卷卷卷了個卷卷閱讀 1,328評論 0 2
  • “兩線同交叉模式”:指在同一天時間里,平滑移動平均線(EX-PMA)指標的短周期(快線)于長周期(慢線)形成金叉且...
    f4f769f861f0閱讀 640評論 0 3
  • 一點墨色一夜長 繚繞過空曠星光 一筆何以書古江 鐫得茫茫刺骨涼 夜深燈難休 影曳人彷徨 偶覺花落歸木樁 忽而夢舟過...
    阿甯Linn閱讀 201評論 1 8

友情鏈接更多精彩內容