Android 项目中资源文件 -- selector篇

样式篇:
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;
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,639评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,093评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,079评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,329评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,343评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,047评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,645评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,565评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,201评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,338评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,014评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,701评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,194评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,685评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,345评论 2 358