Drawable
表示的是一种可以在Canvas
上进行绘制的抽象概念,它的种类有很多,最常见的颜色和图片都可以是一个Drawable
1. Drawable简介
使用方式:
- 定义xml,然后通过
@Drawable
引入布局 - Java代码:new一个所需Drawable并set相关属性,最后加载到布局中。
- 使用
getIntrinsicWidth
,getIntrinsicHeight
两个方法能获得Drawable
的宽高 - 但是并不是每一个
Drawable
都有内部的宽高(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]" />
- 对应
<bitmap>
标签 - 基本使用
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
,可以理解为通过颜色来构造图形,既可以是纯色的图形也可以是具有渐变效果的图形 -
shape
标签创建的Drawable
,但实体类型是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
- 对应的XML标签是
<layer-list>
,它表示一种层次化的Drawable
集合 - 一个
layer-list
可包含多个item
,每个item
表示一个Drawable
。可在android:drawable
中引用一个现有的Drawable
资源,也可在<item>
中自定义Drawable
。 - 默认情况下,
layer-list
中的所有Drawable
都会被缩放至View
的大小。可设置Drawable
相对于View
的上下左右偏移量。另外对于bitmap
,需要使用其android:gravity
来控制图片的显示效果。 -
layer-list
有层次的概念,下面的item
会覆盖上面的item
。通过合理的分层,可实现一些特殊的叠加效果。 - 基本使用
<?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
- 对应于
<selector>
标签,它也表示Drawable
集合 - 每个
Drawable
都对应着一个View
的状态,这样系统就会根据View
的状态来选择合适的Drawable
- 主要用于设置可单机的
View
的背景,最常见的是Button
- 系统根据View的当前状态从
selector
中选择对应的item
,每个item
对应着一个具体的Drawable
,系统自下而上查找,直至匹配到第一条item
,如果没有找到,就会选择默认的item
,因为默认的item
不附带状态,所以它可以匹配任何View
的任何状态
<?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
- 对应于
<level-list>
,它同样表示一个Drawable
集合,集合中的每个Drawable
都有一个等级的概念 - 根据不同的等级,
LevelListDrawable
会切换成对应的Drawable
- 若作为View背景时,可通过
Drawable
的setLevel()
来设置不同的等级来切换具体的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
- 对应于
<transition>
标签,用于实现两个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
- 对应于
<inset>
标签,它可以将其他Drawable内嵌到自己当中,并可以在四周留出一定的间距 - 使用场景:View希望自己的北京比自己的实际区域小
基本使用
<?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>
<!--内嵌到InsetView中-->
</inset>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/inset_drawable"
/>
InsetView
2.8 ScaleDrawable
- 对应于
<scale>
标签,可以根据自己的等级将指定的Drawable缩放到一定的比例 - 等级0表示
ScaleDrawable
不可见,为默认值
<?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
- 对应于
<clip>
标签,它可以根据自己当前的等级来裁剪另一个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