Drawable表示的是一種可以在Canvas上進(jìn)行繪制的抽象概念,它的種類有很多,最常見的顏色和圖片都可以是一個Drawable
1. Drawable簡介
使用方式:
- 定義xml,然后通過
@Drawable引入布局 - Java代碼:new一個所需Drawable并set相關(guān)屬性,最后加載到布局中。
- 使用
getIntrinsicWidth,getIntrinsicHeight兩個方法能獲得Drawable的寬高 - 但是并不是每一個
Drawable都有內(nèi)部的寬高(eg:顏色)
2. Drawable分類
2.1 BitmapDrawable
- 最簡單的
Drawable,表示一張圖片 - XML描述
<?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]" />
- 對應(yīng)
<bitmap>標(biāo)簽 - 基本使用
Drawable/bitmap.xml
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:antialias="true"
android:dither="true"
android:filter="true"
android:gravity="top"
android:tileMode="mirror"
android:src="@drawable/enactus"/>
layout/activity_main.xml
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/bitmap"/>

bitmap Demo
2.2 ShapeDrawable
- 一種常見的
Drawable,可以理解為通過顏色來構(gòu)造圖形,既可以是純色的圖形也可以是具有漸變效果的圖形 -
shape標(biāo)簽創(chuàng)建的Drawable,但實(shí)體類型是GradientDrawable
<?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:topLeftRaidus="integer"
android:topRightRaidus="integer"
android:bottomLeftRaidus="integer"
android:bottomRightRaidus="integer" />
<gradient
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="color"
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>
- 基本使用
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:type="radial" android:centerColor="@color/colorPrimaryDark"
android:startColor="@color/colorPrimary"
android:angle="45" android:centerY="0" android:centerX="0" android:endColor="@color/colorAccent" android:gradientRadius="200dp"/>
<stroke android:width="2dp" android:color="#00FF00"
android:dashGap="5dp" android:dashWidth="5dp"/>
</shape>

ShapeDrawable
2.3 LayerDrawable
- 對應(yīng)的XML標(biāo)簽是
<layer-list>,它表示一種層次化的Drawable集合 - 一個
layer-list可包含多個item,每個item表示一個Drawable??稍?code>android:drawable中引用一個現(xiàn)有的Drawable資源,也可在<item>中自定義Drawable。 - 默認(rèn)情況下,
layer-list中的所有Drawable都會被縮放至View的大小。可設(shè)置Drawable相對于View的上下左右偏移量。另外對于bitmap,需要使用其android:gravity來控制圖片的顯示效果。 -
layer-list有層次的概念,下面的item會覆蓋上面的item。通過合理的分層,可實(shí)現(xiàn)一些特殊的疊加效果。 - 基本使用
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/shape"
android:id="@+id/layer_drawable"
android:top="10dp"
android:right="10dp"
android:left="10dp"
android:bottom="10dp"/>
</layer-list>

LayerDrawable
- 基本使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/remoteViews_content"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/layer_drwable"/>
</LinearLayout>
<?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="2dp"
android:left="2dp"
android:right="2dp">
<shape android:shape="rectangle">
<solid android:color="#ffffff"/>
</shape>
</item>
</layer-list>

LayerDrawable
2.4 StateListDrawable
- 對應(yīng)于
<selector>標(biāo)簽,它也表示Drawable集合 - 每個
Drawable都對應(yīng)著一個View的狀態(tài),這樣系統(tǒng)就會根據(jù)View的狀態(tài)來選擇合適的Drawable - 主要用于設(shè)置可單機(jī)的
View的背景,最常見的是Button - 系統(tǒng)根據(jù)View的當(dāng)前狀態(tài)從
selector中選擇對應(yīng)的item,每個item對應(yīng)著一個具體的Drawable,系統(tǒng)自下而上查找,直至匹配到第一條item,如果沒有找到,就會選擇默認(rèn)的item,因?yàn)槟J(rèn)的item不附帶狀態(tài),所以它可以匹配任何View的任何狀態(tài)
<?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]" />
<!-- 其他item -->
</selector>
基本使用
StateListDrawable stateListDrawable = (StateListDrawable) getResources().getDrawable(R.drawable.state_list_drawable);
Button button = findViewById(R.id.btn);
button.setBackgroundDrawable(stateListDrawable);
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape" android:state_pressed="true"/>
</selector>

StateListDrawable
2.5 LevelListDrawable
- 對應(yīng)于
<level-list>,它同樣表示一個Drawable集合,集合中的每個Drawable都有一個等級的概念 - 根據(jù)不同的等級,
LevelListDrawable會切換成對應(yīng)的Drawable - 若作為View背景時,可通過
Drawable的setLevel()來設(shè)置不同的等級來切換具體的Drawable。 - 若作為
ImageView的前景,可通過ImageView的setImageLevel()來切換。
基本使用
final LevelListDrawable levelListDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.level_list_drawable);
Button button = findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
levelListDrawable.setLevel(1);
}
});
button.setBackgroundDrawable(levelListDrawable);
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/shape"
android:maxLevel="1"
android:minLevel="1"/>
<item
android:drawable="@drawable/layer_drwable"
android:maxLevel="0"/>
</level-list>

LevelListDrawable
2.6 TransitionDrawable
- 對應(yīng)于
<transition>標(biāo)簽,用于實(shí)現(xiàn)兩個Drawable之間的淡入淡出效果
基本使用
TextView textView = findViewById(R.id.text);
TransitionDrawable transitionDrawable = (TransitionDrawable)textView.getBackground();
transitionDrawable.startTransition(1000);
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/text"
android:background="@drawable/transition_drawable"/>
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/shape"/>
<item android:drawable="@color/colorPrimaryDark"/>
</transition>

TransitionDrawable
2.7 InsetDrawable
- 對應(yīng)于
<inset>標(biāo)簽,它可以將其他Drawable內(nèi)嵌到自己當(dāng)中,并可以在四周留出一定的間距 - 使用場景:View希望自己的北京比自己的實(shí)際區(qū)域小
基本使用
<?xml version="1.0" encoding="utf-8"?>
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@[package:]drawable/drawable_resource"
android:inset="dimension"
android:insetTop="dimension"
android:insetRight="dimension"
android:insetBottom="dimension"
android:insetLeft="dimension" />
<?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>
<solid android:color="@color/colorPrimaryDark"/>
</shape>
<!--內(nèi)嵌到InsetView中-->
</inset>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/inset_drawable"
/>

InsetView
2.8 ScaleDrawable
- 對應(yīng)于
<scale>標(biāo)簽,可以根據(jù)自己的等級將指定的Drawable縮放到一定的比例 - 等級0表示
ScaleDrawable不可見,為默認(rèn)值
<?xml version="1.0" encoding="utf-8"?>
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@[package:]drawable/drawable_resource"
android:scaleGravity="[top | bottom | left | right |
center_vertical | center_horizontal | center |
fill_vertical | fill_horizontal | fill |
clip_vertical | clip_horizontal]"
android:scaleWidth="percentage"
android:scaleHeight="percentage" />
基本使用
ImageView imageView = findViewById(R.id.imageView);
ScaleDrawable scaleDrawable = (ScaleDrawable) imageView.getBackground();
scaleDrawable.setLevel(1);
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/scale_drawable"
/>
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:scaleHeight="70%"
android:scaleWidth="70%"
android:scaleGravity="center"
android:drawable="@drawable/enactus">
</scale>

ScaleDrawable
2.9 ClipDrawable
- 對應(yīng)于
<clip>標(biāo)簽,它可以根據(jù)自己當(dāng)前的等級來裁剪另一個Drawable - 通過
android:clipOrientation和android:gravity兩個屬性來控制裁剪
<?xml version="1.0" encoding="utf-8"?>
<clip
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@[package:]drawable/drawable_resource"
android:clipOrientation="[vertical | horizontal]"
android:gravity="[top | bottom | left | right |
center_vertical | center_horizontal | center |
fill_vertical | fill_horizontal | fill |
clip_vertical | clip_horizontal]" />
基本使用
ImageView imageView = findViewById(R.id.imageView);
ClipDrawable clipDrawable = (ClipDrawable) imageView.getDrawable();
clipDrawable.setLevel(5000);
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/clip_drawable"
/>
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="@drawable/enactus"
android:gravity="bottom">
</clip>

clipDrawable
參考資料:
Android中常用的Drawable
3. 自定義Drawable
- Drawable的使用范圍:一是作為ImageView中的圖箱來顯示,另外一個就是作為View的背景
- 核心是
Draw方法,可以通過重寫Drawable的Draw方法來自定義Drawable