掌握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%。