StateListDrawable:状态Drawable
控件处于不同的状态,如点击、释放、勾选、不可用等状态时设置不同的样式。在代码中可以通过条件判断去根据不同的状态进行判断再设置不同的属性,这样做太麻烦了。
Android给我们的drawable提供了便捷的设置方式,就是自定义一个selector背景样式,给不同的状态属性设置对应的drawable资源。更多Drawable详见Android Drawable。
1、StateListDrawable
StateListDrawable将多个图形图像集中到一个Drawable,并用更具控件的状态值替换可见项。
1.1、介绍
StateListDrawable是在 XML 文件中定义的可绘制对象,它会根据对象状态,使用多个不同的图像来表示同一个图形。例如,Button 微件可以是多种不同状态(按下、聚焦或这两种状态都不是)中的其中一种,并且您可利用状态列表可绘制对象,为每种状态提供不同的背景图片。
1.2、语法
先在res/drawablez资源目录下建一个drawable背景资源文件,根标签选择<selector/>。基本语法如下:
<?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>1.3、使用
①代码中使用
R.drawable.filename②xml布局中引用
@[package:]drawable/filename2、元素介绍
介绍一下使用XML定义StateListDrawable用到的各个属性的意义,参考Drawable State list。
2.1、根标签<selector>
StateListDrawable必须用<selector>作为根标签,该标签底下有三个属性:
①android:constantSize:布尔值。如果可绘制对象报告的内部大小在状态变更时保持不变,则值为“true”(大小是所有状态的最大值);如果大小根据当前状态而变化,则值为“false”。默认值为 false。
②android:dither:布尔值。值为“true”时,将在位图的像素配置与屏幕不同时(例如:ARGB 8888 位图和 RGB 565 屏幕)启用位图的抖动;值为“false”时则停用抖动。默认值为 true。
③android:variablePadding:布尔值。如果可绘制对象的内边距应根据选择的当前状态而变化,则值为“true”;如果内边距应保持不变(基于所有状态的最大内边距),则值为“false”。启用此功能要求您在状态变更时处理执行布局,这通常不受支持。默认值为 false。
2.2、元素标签<item>
定义在特定状态使用的可绘制对象,使用<item>并在内部指定资源及其对应的状态。
①android:state_pressed:true指当用户点击或者触摸该控件的状态。默认为false;一般用于设置按钮颜色/图片的设置。
②android:state_focused:ture指当前控件获得焦点时的状态。默认为false;一般用于EdiText。
③android:state_hovered:true表示光标移动到当前控件上的状态。默认为false;光标是否悬停,通常与state_focused 相同,它是4.0的新特性,一般用于EdiText。
④android:state_selected:true表示被选择的状态,例如在一个下拉列表中用方向键下选择其中一个选项。这个和focus的区别,selected是focus不充分的情况。比如一个listview获得焦点(focus),而用方向键选择了其中的一个item(selected)
⑤android:state_checkable:ture表示可以被勾选的状态。仅当控件具有被勾选和不被勾选的状态间转换时才起作用。
⑥android:state_checked:true表示当前控件处于被勾选(check的状态)
⑦android:state_enabled:true表示当前控件出于可用的状态。比如可以被点击
⑧android:state_activated:true表示当前控件被激活的状态
⑨android:state_window_focused:true表示当前控件出于最前端时,应用窗口获得焦点的状态
StateListDrawable中一个方法addState(int[] stateSet, Drawable drawable),用代码的方式设置上面的状态及对应的Drawable资源。
/**
* Add a new image/string ID to the set of images.
*
* @param stateSet - An array of resource Ids to associate with the image.
* Switch to this image by calling setState().
* @param drawable -The image to show.
*/
public void addState(int[] stateSet, Drawable drawable)示例:
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, getDrawable(R.drawable.git));3、示例
每个<item>都必须要有drawable,可以不设置对应的属性,表示默认的drawable:
<item android:drawable="@drawable/bg_default" />3.1、定义StateListDrawable
自定义一个简单的StateListDrawable资源文件:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bg_pressed_false" android:state_pressed="false" />
<item android:drawable="@drawable/bg_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/bg_hovered" android:state_enabled="true" />
<item android:drawable="@drawable/bg_default" />
</selector>示例效果如下:

3.2、注意
在每个状态变更期间,将从上到下遍历状态列表,并使用第一个与当前状态匹配的项目 —此选择并非基于“最佳匹配”,而是选择符合状态最低条件的第一个项目。因为第一个如果是通用的,后面都不会被使用到:
selector 标签嵌套 shape,可以直接定义也可以引用shape文件。但是不要使用过于复杂的<bitmap>等,找不到文件会抛出异常,Android可能是不是的在哪里有坑!
参考资料:
Reference > StateListDrawable">Android Developers > Reference > StateListDrawable


