样式篇:
Android 项目中资源文件 -- shape篇
Android 项目中资源文件 -- selector篇
Android 项目中资源文件 -- layer-list篇
在我们的日常开发中,经常会遇到一些这样的需求:
- 当 view 被点击的时候显示一个其他的颜色,松开之后恢复原本的颜色
- 状态开关
等等,一些需求的时候,为了更方便开发,官方推出了一个叫做 selector
的东西。今天这篇文章就来整理一下 selector
相关的属性和使用。
介绍
可绘制对象资源中的状态列表 (StateListDrawable )
这有一个官方的文档 谷歌 selector 官方介绍, 感兴趣的可以自己去看看。
StateListDrawable 是在 XML 中定义的可绘制对象,它根据对象的状态,使用多个不同的图像来表示同一个图形。例如,Button 小部件可以是多种不同状态(按下、聚焦或这两种状态都不是)中的其中一种,而且可以利用状态列表可绘制对象为每种状态提供不同的背景图片。
您可以在 XML 文件中描述状态列表。每个图形由单一
<selector>
元素内的<item>
元素表示。每个<item>
均使用各种属性来描述应用作可绘制对象的图形的状态。在每个状态变更期间,将从上到下遍历状态列表,并使用第一个与当前状态匹配的项目 —此选择并非基于“最佳匹配”,而是选择符合状态最低条件的第一个项目。
文件位置:
res/drawable/filename.xml
文件名用作资源 ID。
编译资源的数据类型:
指向 StateListDrawable 的资源指针。
资源引用:
在 Java 中:R.drawable.filename
在 XML 中:@[package:]drawable/filename
语法
<?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"]
//被选中,它与focus state并不完全一样
android:state_selected=["true" | "false"]
//组件是否能被check
android:state_checkable=["true" | "false"]
//被checked了
android:state_checked=["true" | "false"]
//能够接受触摸或者点击事件
android:state_enabled=["true" | "false"]
// 被激活
android:state_activated=["true" | "false"]
//应用程序是否在前台
android:state_window_focused=["true" | "false"] />
</selector>
元素:
<selector>
必备。这必须是根元素。包含一个或多个 <item>
元素。
<item>
定义要在某些状态期间使用的可绘制对象,如其属性所述。必须是 <selector>
元素的子项。
item属性:
android:drawable
可绘制对象资源。必备。引用可绘制对象资源。
android:state_xx
不同的状态。
属性(android:state_xx) | 含义 |
---|---|
android:state_pressed | 是否按下,如一个按钮触摸或者点击 |
android:state_focused | 是否取得焦点,比如用户选择了一个文本框 |
android:state_hovered | 光标是否悬停,通常与focused state相同,它是4.0的新特性 |
android:state_selected | 是否被选中,它与focus state并不完全一样,如一个list view 被选中的时候,它里面的各个子组件可能通过方向键,被选中了。 |
android:state_checkable | 组件是否能被check。如:RadioButton是可以被check的 |
android:state_checked | 是否被checked了,如:一个RadioButton可以被check了 |
android:state_enabled | 是否能够接受触摸或者点击事件 |
android:state_activated | 是否被激活(很少用 我自己是没有用到过) |
android:state_window_focused | 应用程序是否在前台,当有通知栏被拉下来或者一个对话框弹出的时候应用程序就不在前台了 |
注意: 如果有多个item,那么程序将自动从上到下进行匹配,最先匹配的将得到应用。(不是通过最佳匹配)
如果一个item没有任何的状态说明,那么它将可以被任何一个状态匹配。
使用实践
我们实现一个CheckBox的不同状态显示不同。
check_box.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="@drawable/check_box_on" />
<item android:state_checked="false" android:drawable="@drawable/check_box_off"/>
</selector>
android:drawable="@drawable/check_box_on"
是 drawable
文件下的的图片文件。
- 在我们
layout
文件中
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/check_box_type"
android:button="@null"
android:clickable="false" />
-
java
代码中
checkBox.setCheck(true)
或者
checkBox.setCheck(false)
这样就可以改变 CheckBox 展示的样式。
selector 工具类
/**
* 动态设置 点击事件 selector 的工具类 可以从本地添加 也可以从网络添加
*/
public class SelectorUtil {
/**
* 从 drawable 获取图片 id 给 Imageview 添加 selector
* @param context 调用方法的 Activity
* @param idNormal 默认图片的 id
* @param idPress 点击图片的 id
* @param iv 点击的 view
*/
public static void addSelectorFromDrawable(Context context , int idNormal, int idPress,ImageView iv){
StateListDrawable drawable = new StateListDrawable();
Drawable normal = context.getResources().getDrawable(idNormal);
Drawable press = context.getResources().getDrawable(idPress);
drawable.addState(new int[]{android.R.attr.state_pressed},press);
drawable.addState(new int[]{-android.R.attr.state_pressed},normal);
iv.setBackgroundDrawable(drawable);
}
/**
* 从 drawable 获取图片 id 给 Button 添加 selector
* @param context 调用方法的 Activity
* @param idNormal 默认图片的 id
* @param idPress 点击图片的 id
* @param button 点击的 view
*/
public static void addSelectorFromDrawable(Context context , int idNormal, int idPress,Button button){
StateListDrawable drawable = new StateListDrawable();
Drawable normal = context.getResources().getDrawable(idNormal);
Drawable press = context.getResources().getDrawable(idPress);
drawable.addState(new int[]{android.R.attr.state_pressed},press);
drawable.addState(new int[]{-android.R.attr.state_pressed},normal);
button.setBackgroundDrawable(drawable);
}
/**
* 从网络获取图片 给 ImageView 设置 selector
* @param clazz 调用方法的类
* @param normalUrl 获取默认图片的链接
* @param pressUrl 获取点击图片的链接
* @param imageView 点击的 view
*/
public static void addSeletorFromNet(final Class clazz, final String normalUrl, final String pressUrl, final ImageView imageView){
new AsyncTask<Void,Void,Drawable>(){
@Override
protected Drawable doInBackground(Void... params) {
StateListDrawable drawable = new StateListDrawable();
Drawable normal = loadImageFromNet(clazz,normalUrl);
Drawable press = loadImageFromNet(clazz, pressUrl);
drawable.addState(new int[]{android.R.attr.state_pressed},press);
drawable.addState(new int[]{-android.R.attr.state_pressed},normal);
return drawable;
}
@Override
protected void onPostExecute(Drawable drawable) {
super.onPostExecute(drawable);
imageView.setBackgroundDrawable(drawable);
}
}.execute();
}
/**
*
* 从网络获取图片 给 Button 设置 selector
* @param clazz 调用方法的类
* @param normalUrl 获取默认图片的链接
* @param pressUrl 获取点击图片的链接
* @param button 点击的 view
*/
public static void addSeletorFromNet(final Class clazz, final String normalUrl, final String pressUrl, final Button button){
new AsyncTask<Void,Void,Drawable>(){
@Override
protected Drawable doInBackground(Void... params) {
StateListDrawable drawable = new StateListDrawable();
Drawable normal = loadImageFromNet(clazz,normalUrl);
Drawable press = loadImageFromNet(clazz, pressUrl);
drawable.addState(new int[]{android.R.attr.state_pressed},press);
drawable.addState(new int[]{-android.R.attr.state_pressed},normal);
return drawable;
}
@Override
protected void onPostExecute(Drawable drawable) {
super.onPostExecute(drawable);
button.setBackgroundDrawable(drawable);
}
}.execute();
}
/**
* 从网络获取图片
* @param clazz 调用方法的类
* @param netUrl 获取图片的链接
* @return 返回一个 drawable 类型的图片
*/
private static Drawable loadImageFromNet(Class clazz, String netUrl) {
Drawable drawable =null;
try {
drawable = Drawable.createFromStream(new URL(netUrl).openStream(), "netUrl.jpg");
} catch (IOException e) {
MyLog.e(clazz.getName(),e.getMessage());
}
return drawable;
}
}