六、Drawable

掌握Drawable可以做出一些特殊的效果.

1.Drawable的內部寬高

通過getIntrinsicWidth和getIntrinsicHeight這兩個方法可以獲取到。並不是所有的Drawable都有內部寬高,比如一張圖片所形成的的Drawable,它的內部寬高就是圖片的寬高,但是一個顏色所形成的的Drawable,就沒有內部寬高的概念。
另外需要注意的是,Drawable的內部寬高不等同於它的大小,一般來說,Drawable是沒有大的概念的,當用作View的背景的時候,Drawable會被拉伸至View的同等大小。

2.Drawable的分類

2.1.BitmapDrawable

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:antialias=["true" | "false"]
    android:dither=["true" | "false"]
    android:filter=["true" | "false"]
    android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                      "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                      "center" | "fill" | "clip_vertical" | "clip_horizontal"]
    android:mipMap=["true" | "false"]
    android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />

表示的就是一張圖片,在實際的開發中,可以直接引用原始的圖片即可,也可以通過xml的方式來描述。
src:圖片的資源id

antialias:是否開啓圖片的抗鋸齒,開啓後會讓圖片更加圓滑,同時會在一定的程度上面降低圖片的清晰度,但是這個降低的幅度較低以至於可以忽略。因此抗鋸齒選項應該開啓。

dither:是否開啓抖動效果。根據分析,抖動效果應該開啓。

filter:是否開啓過濾效果。當圖片尺寸被拉伸或者壓縮的時候,開啓過濾效果可以保持較好的顯示效果,因此應當開啓。

gravity:當圖片的尺寸小於容器的尺寸的時候,設置此選項可以對圖片進行定位。

mipMap:圖片相關的處理技術叫紋理映射,默認值爲false,開發中此選項不常用。

tileMode:平鋪模式。disabled表示關閉平鋪模式,默認值。當開啓平鋪模式之後gravity屬性會被忽略。

repeat表示簡單的水平和豎直方向的平鋪效果;

mirror表示在水平和豎直方向上的鏡面投影效果;

clamp表示圖片四周的像素會擴展到周圍區域。

2.2.NinePatchDrawable

<?xml version="1.0" encoding="utf-8"?>
<nine-patch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@[package:]drawable/drawable_resource"
    android:dither=["true" | "false"] />

xml中的屬性和BitmapDrawable中標籤的屬性是一樣的,表示一張.9格式的圖片。.9圖片可以自動地根據所需的寬/高進行相應的縮放並保證不失真,和BitmapDrawable一樣,在實際開發中可以直接引用,實際使用過程中發現bitmap標籤也可以使用.9圖。

2.3.ShapeDrawable

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape=["rectangle" | "oval" | "line" | "ring"] >
    <corners
        android:radius="integer"
        android:topLeftRadius="integer"
        android:topRightRadius="integer"
        android:bottomLeftRadius="integer"
        android:bottomRightRadius="integer" />
    <gradient
        android:angle="integer"
        android:centerX="integer"
        android:centerY="integer"
        android:centerColor="integer"
        android:endColor="color"
        android:gradientRadius="integer"
        android:startColor="color"
        android:type=["linear" | "radial" | "sweep"]
        android:useLevel=["true" | "false"] />
    <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:圖形的形狀,矩形,橢圓,橫線,圓環,默認矩形,另外,line和ring這兩個選項必須通過stroke指定閒的寬度和顏色等信息。

針對ring這個環狀,有5個特殊的屬性:
android:innerRadius圓環的內半徑,和android:innerRadiusRatio同時存在時,以android:innerRadius爲準。
android:innerRadiusRatio內半徑佔整個Drawable寬度的比例,默認爲9。如果爲n,那麼內半徑=寬度/n
android:thickness圓環的厚度,即外半徑減去內半徑的大小,和android:thicknessRatio同時存在時,以android:thickness爲準。
android:thicknessRatio厚度佔整個Drawable寬度的比例,默認值爲3。如果爲n,那麼厚度=寬度/n
android:useLevel一般應該使用false,否則有可能無法達到預期的顯示效果,除非被當做LevelListDrawable。

corners:表示shape的四個角的角度。只適用於矩形shape,這裏的角度指的是圓角的程度用px來表示。

android:radius爲四個角同時設定相同的角度,優先級較低,會被其他四個屬性覆蓋。
android:topLeftRadius設定左上角的角度
android:topRightRadius設定右上角的角度
android:bottomLeftRadius設定左下角的角度
android:bottomRightRadius設定右下角的角度

gradient:與solid標籤是互相排斥的,其中solid表示純色填充,而gradient表示漸變效果。

android:angle漸變的角度。默認爲0,其值必須爲45的倍數,0表示從左到右,90表示從下到上。
android:centerX漸變的中心點的橫座標
android:centerY漸變的中心點的縱座標
android:startColor漸變的起始色
android:centerColor漸變的中間色
android:endColor漸變的結束色
android:gradientRadius漸變半徑,僅當android:type爲radial有效
android:useLevel一般爲false,當Drawable作爲StateListDrawable使用時爲true
android:type漸變的類型,有linear線性漸變,radial徑向漸變,sweep掃描線漸變三種,默認爲線性漸變。

solid:這個表示純色填充,通過color即可指定shape中填充的顏色。

stroke:shape的描邊。
android:width描邊的寬度,越大則shape的邊緣線就會看起來約粗
android:color描邊的顏色
android:dashWidth組成虛線的線段的寬度
android:dashGap組成虛線的線段之間的間隔,間隔越大看起來空隙就越大
注意:如果android:dashWidth和android:dashGap有任何一個爲0,那麼虛線效果將不能生效

padding:表示空白,但是它表示的不是shape的空白,而是包含它的view的空白。

size:shape的大小,屬性android:width,android:height。

表示shape的固有大小,一般來說不是shape最終顯示的大小,shape沒有寬高的概念,作爲view的背景會自適應view的寬高。Drawable的兩個方法getIntrinsicWidth和getIntrinsicHeight表示的是Drawable的固有寬高,對於有些Drawable比如圖片來說,它的固有寬高就是圖片的尺寸,對於shape來說,默認情況下,它是沒有固有寬高這個概念的,這個時候那兩個方法就會返回-1,但是如果通過size標籤設置寬高信息,shape就有了所謂的固有寬高。

總結來說,size標籤設置的寬高就是ShapeDrawable的固有寬高,但是作爲view的背景時,shape還會被拉伸或者縮小爲view的大小。

2.4.LayerDrawable

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</layer-list>

表示一種層次化的Drawable集合,通過將不同的Drawable放置在不同的層上面從而達到一種疊加後的效果。這些屬性分別表示Drawable相對於View的上下左右的偏移量。

類似微信的文本輸入框:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#0AC39E"/>
        </shape>
    </item>
    <item android:bottom="6dp">
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF"/>
        </shape>
    </item>
    <item
        android:bottom="1dp"
        android:left="1dp"
        android:right="1dp">
        <shape android:shape="rectangle">
            <solid android:color="#FFFFFF"/>
        </shape>
    </item>
</layer-list>

2.5.StateListDrawable

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:constantSize=["true" | "false"]
    android:dither=["true" | "false"]
    android:variablePadding=["true" | "false"] >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:state_pressed=["true" | "false"]
        android:state_focused=["true" | "false"]
        android:state_hovered=["true" | "false"]
        android:state_selected=["true" | "false"]
        android:state_checkable=["true" | "false"]
        android:state_checked=["true" | "false"]
        android:state_enabled=["true" | "false"]
        android:state_activated=["true" | "false"]
        android:state_window_focused=["true" | "false"] />
</selector>

表示Drawable集合,每個Drawable對應着View的一種狀態,這樣系統就會根據View的狀態來選擇合適的Drawable。
屬性:
android:constantSizeDrawable的固有大小是否不隨着其狀態的改變而改變,默認值爲false。
android:dither抖動效果是否開啓,默認爲true
android:variablePaddingDrawable的padding表示是否隨着狀態的改變而改變,默認false。
item標籤表示一個具體的Drawable。

2.6.LevelListDrawable

<?xml version="1.0" encoding="utf-8"?>
<level-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@drawable/drawable_resource"
        android:maxLevel="integer"
        android:minLevel="integer" />
</level-list>

表示Drawable集合,集合中的每個Drawable都有一個等級的概念,根據不同的等級,Drawable會切換爲對應的Drawable。
作爲View的背景的時候,可以通過Drawable的setLevel方法來設置不同的等級從而切換具體的Drawable,被用作ImageView的前景時,可以通過ImageView的setImageLevel方法來切換Drawable。範圍0-10000。

2.7.TransitionDrawable

<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="@[package:]drawable/drawable_resource"
        android:id="@[+][package:]id/resource_name"
        android:top="dimension"
        android:right="dimension"
        android:bottom="dimension"
        android:left="dimension" />
</transition>

表示兩個Drawable之間的淡入淡出效果。
可以使用它的startTransition和reverseTransition方法來實現淡入淡出的效果以及它的逆過程。

2.8.InsetDrawable

<?xml version="1.0" encoding="utf-8"?>
<inset
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:insetTop="dimension"
    android:insetRight="dimension"
    android:insetBottom="dimension"
    android:insetLeft="dimension" />

可以將其他Drawable內嵌到自己當中,並可以在四周留出一定的間距。當一個view希望自己的背景比自己的實際區域小的時候,可以採用它實現。

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:insetBottom="15dp"
    android:insetLeft="15dp"
    android:insetRight="15dp"
    android:insetTop="15dp" >
    <shape android:shape="rectangle" >
        <solid android:color="#ff0000" />
    </shape>
</inset>

shape距離view的邊界15dp。

2.9.ScaleDrawable

<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                          "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                          "center" | "fill" | "clip_vertical" | "clip_horizontal"]
    android:scaleHeight="percentage"
    android:scaleWidth="percentage" />

可以根據自己的等級level將指定的Drawable縮放到一定的比例。android:scaleHeight,android:scaleWidth分別表示對指定Drawable寬和高的縮放比例,以百分比的形式表示。想要ScaleDrawable可見,需要等級不能爲0。範圍0-10000。

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/image_bg"
    android:scaleHeight="70%"
    android:scaleWidth="70%"
    android:scaleGravity="center" />
View testScale = findViewById(R.id.test_scale);
ScaleDrawable testScaleDrawable = (ScaleDrawable) testScale.getBackground();
testScaleDrawable.setLevel(10);

2.10.ClipDrawable

<?xml version="1.0" encoding="utf-8"?>
<clip
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/drawable_resource"
    android:clipOrientation=["horizontal" | "vertical"]
    android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
                     "fill_vertical" | "center_horizontal" | "fill_horizontal" |
                     "center" | "fill" | "clip_vertical" | "clip_horizontal"] />

可以根據自己的等級level來裁剪另一個Drawable。

將一張圖片從上到下裁剪:

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="vertical"
    android:drawable="@drawable/image_bg"
    android:gravity="bottom" />
ImageView testClip = (ImageView) findViewById(R.id.test_clip);
ClipDrawable testClipDrawable = (ClipDrawable) testClip.getDrawable();
testClipDrawable.setLevel(8000);

等級設置爲8000表示,裁剪2000,在頂部裁掉20%。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章