Android-动态设置selector

3,543 阅读2分钟

为啥会涉及到动态设置selector?

其实我们正常在res文件夹添加一个xml就可,之所以涉及到动态设置selector,是因为selector里面不同状态的drawable需要动态设置不同值的radius.

首先selector里面有几种常见状态呢?

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/standard_gold_gradient_button_pre" />
    <item android:state_focused="true" android:drawable="@drawable/standard_gold_gradient_button_pre" />
    <item android:state_selected="true" android:drawable="@drawable/standard_gold_gradient_button_pre" />
    <item android:state_enabled="false" android:drawable="@drawable/standard_gold_gradient_button_disable" />
    <item android:drawable="@drawable/standard_gold_gradient_button_normal" />
</selector>

然后设置对应的drawable,最后一种是默认状态.

上面是xml设置,那动态设置是怎么设置呢?

 /**
     * 设置button各种状态的颜色。
     *
     * @param pressDrawableId   按下去的颜色
     * @param focusDrawableId   获取焦点的颜色
     * @param disableDrawableId 不能点击的颜色
     * @param normalDrawableId  默认状态下颜色
     * @param radiusHeight      圆角的值
     */
    private void setBgDrawable(@DrawableRes int pressDrawableId, @DrawableRes int focusDrawableId,
                               @DrawableRes int disableDrawableId,
                               @DrawableRes int normalDrawableId, float radiusHeight) {
        StateListDrawable stateListDrawable = new StateListDrawable();
        GradientDrawable buttonPress = (GradientDrawable) context.getResources()
                .getDrawable(pressDrawableId);
        if (radiusHeight > 0) {
            buttonPress.setCornerRadius(radiusHeight);
        }
        stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, buttonPress);

        GradientDrawable buttonFocus = (GradientDrawable) context.getResources()
                .getDrawable(focusDrawableId);
        if (radiusHeight > 0) {
            buttonFocus.setCornerRadius(radiusHeight);
        }
        stateListDrawable.addState(new int[]{android.R.attr.state_focused}, buttonFocus);

        GradientDrawable buttonDisable = (GradientDrawable) context.getResources()
                .getDrawable(disableDrawableId);
        if (radiusHeight > 0) {
            buttonDisable.setCornerRadius(radiusHeight);
        }
        stateListDrawable.addState(new int[]{-android.R.attr.state_enabled}, buttonDisable);

        GradientDrawable buttonNormal = (GradientDrawable) context.getResources()
                .getDrawable(normalDrawableId);
        if (radiusHeight > 0) {
            buttonNormal.setCornerRadius(radiusHeight);
        }
        stateListDrawable.addState(new int[]{}, buttonNormal);
        setBackground(stateListDrawable);
    }

注意一下,这最后一种是默认状态的颜色 以上内容中:
1.StateListDrawable来实现动态Selector效果
2.android.R.attr.state_pressed为点击效果,-android.R.attr.state_pressed为非点击效果(示例中调整了透明度来区别)
3.GradientDrawable为设置背景渐变色

跟进:如果drabwable没有渐变色是不需要转化成GradientDrawable 直接转成drawable即可

注意和了解

selector作为drawable资源时,item指定android:drawable属性,并放于drawable目录下; selector作为color资源时,item指定android:color属性,并放于color目录下; color资源也可以放于drawable目录,引用时则用@drawable来引用,但不推荐这么做,drawable资源和color资源最好还是分开; android:drawable属性除了引用@drawable资源,也可以引用@color颜色值;但android:color只能引用@color; item是从上往下匹配的,如果匹配到一个item那它就将采用这个item,而不是采用最佳匹配的规则;所以设置默认的状态,

** 注意1:一定要写在最后,如果写在前面,则后面所有的item都不会起作用了**
** 注意2:因为我设置了clickable false后 我的press focus 点击 都不会有颜色变化 反应,需要我先设置了clickable true后 我的press focus 点击才会有颜色变化 反应**

参考文档:
1.Android 02 selector状态选择器
2.android动态添加selector选择器代码
3.Android中使用代码动态设置Selector