Android:可以在可绘制选择器中使用字符串/枚举吗? [英] Android: Is it possible to use string/enum in drawable selector?

查看:74
本文介绍了Android:可以在可绘制选择器中使用字符串/枚举吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

第1季度:有没有人设法让自定义字符串/枚举属性在xml选择器中工作?我通过遵循[1]得到了一个布尔属性,但没有一个字符串属性.

Q1: Has anyone managed to get custom string/enum attribute working in xml selectors? I got a boolean attribute working by following [1], but not a string attribute.

感谢您的回答.目前,Android仅支持布尔选择器.查看原因的可接受答案.

Thanks for answers. Currently android supports only boolean selectors. See accepted answer for the reason.

我打算实现一个复杂的自定义按钮,其外观取决于两个变量.其他将是布尔属性(是或否),而另一个将是类类别的属性(具有许多不同的可能值).我的计划是使用布尔值和字符串(或可能是枚举?)属性.我希望可以使用boolean和string属性在xml选择器中定义UI.

I'm planning to implement a little complex custom button, whose appearance depends on two variables. Other will be a boolean attribute (true or false) and another category-like attribute (has many different possible values). My plan is to use boolean and string (or maybe enum?) attributes. I was hoping I could define the UI in xml selector using boolean and string attribute.

第二季度:为什么在[1]中的onCreateDrawableState()中,布尔属性仅在它们为true时才被合并?

Q2: Why in [1] the onCreateDrawableState(), boolean attributes are merged only if they are true?

注意:这只是一个测试应用程序,用于确定xml选择器中是否可以使用string/enum属性.我知道我可以在没有自定义属性的情况下设置按钮的文本颜色.

NOTE: This is just a test app to figure out if string/enum attribute is possible in xml selector. I know that I could set button's textcolor without a custom attribute.

在演示应用程序中,我使用boolean属性将按钮背景设置为深色/明亮,并使用string属性设置文本颜色,例如{"red","green","blue"}中的一种.属性在/res/values/attrs.xml

In my demo application, I use a boolean attribute to set button background to dark/bright and string attribute to set text color, one of {"red", "green", "blue"}. Attributes are defined in /res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomButton">
        <attr name="make_dark_background" format="boolean" />
        <attr name="str_attr" format="string" />
    </declare-styleable>
</resources>

这是我要实现的选择器:

Here are the selectors I want to achieve:

@ drawable/custom_button_background(有效)

@drawable/custom_button_background (which works)

<?xml version="1.0" encoding="utf-8"?>
<selector 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.customstringattribute">

    <item app:make_dark_background="true" android:drawable="@color/dark" />
    <item android:drawable="@color/bright" />

</selector>

@ color/custom_button_text_color(无效)

@color/custom_button_text_color (which does not work)

<selector 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.customstringattribute">

    <item app:str_attr="red" android:color="@color/red" />
    <item app:str_attr="green" android:color="@color/green" />
    <item app:str_attr="blue" android:color="@color/blue" />

    <item android:color="@color/grey" />

</selector>

这是将自定义按钮背景连接到布尔选择器,以及将文本颜色连接到字符串选择器的方式.

Here is how custom button background is connected to boolean selector, and text color is connected to string selector.

<com.example.customstringattribute.MyCustomButton
    ...
    android:background="@drawable/custom_button_background"
    android:textColor="@color/custom_button_text_color"
    ...
/>

这是在init()方法中加载属性的方式:

Here is how attributes are loaded in the init() method:

private void init(AttributeSet attrs) {

    TypedArray a = getContext().obtainStyledAttributes(attrs,
            R.styleable.MyCustomButton);

        final int N = a.getIndexCount();
        for (int i = 0; i < N; ++i)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
                case R.styleable.MyCustomButton_str_attr:
                    mStrAttr = a.getString(attr);
                    break;
                case R.styleable.MyCustomButton_make_dark_background:
                    mMakeDarkBg  = a.getBoolean(attr, false);
                    break;
            }
        }
        a.recycle();
}

我有用于属性的int []数组

I have the int[] arrays for the attributes

private static final int[] MAKE_DARK_BG_SET = { R.attr.make_dark_background };
private static final int[] STR_ATTR_ID = { R.attr.str_attr };

然后将这些int []数组合并为可绘制状态

And those int[] arrays are merged to drawable state

@Override
protected int[] onCreateDrawableState(int extraSpace) {
    Log.i(TAG, "onCreateDrawableState()");
    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    if(mMakeDarkBg){
        mergeDrawableStates(drawableState, MAKE_DARK_BG_SET);
    }
    mergeDrawableStates(drawableState, STR_ATTR_ID);
    return drawableState;
}

我的属性设置器方法中也有refreshDrawableState():

I also have refreshDrawableState() in my attribute setter methods:

public void setMakeDarkBg(boolean makeDarkBg) {
    if(mMakeDarkBg != makeDarkBg){
        mMakeDarkBg = makeDarkBg;
        refreshDrawableState();
    }
}

public void setStrAttr(String str) {
    if(mStrAttr != str){
        mStrAttr = str;
        refreshDrawableState();
    }
}

[1]:如何添加自定义按钮状态

推荐答案

第一季度:

打开StateListDrawable.java的源代码时,您可以在读取可绘制xml选择器的inflate方法中看到以下代码: https://android. googlesource.com/platform/frameworks/base/+/refs/heads/master/graphics/java/android/graphics/drawable/StateListDrawable.java

When you open the source-code of StateListDrawable.java, you can see this piece of code in the inflate method that reads the drawable xml selector: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/graphics/java/android/graphics/drawable/StateListDrawable.java

        ...

        for (i = 0; i < numAttrs; i++) {
            final int stateResId = attrs.getAttributeNameResource(i);
            if (stateResId == 0) break;
            if (stateResId == com.android.internal.R.attr.drawable) {
                drawableRes = attrs.getAttributeResourceValue(i, 0);
            } else {
                states[j++] = attrs.getAttributeBooleanValue(i, false)
                        ? stateResId
                        : -stateResId;
            }
        }
        ...

attrs<selector>中每个<item>元素的属性.

attrs are the attributes of each <item> element in the <selector>.

在此for循环中,它获取android:drawable,各种android:state_xxxx和自定义app:xxxx属性.除了android:drawable属性之外的所有属性似乎都只解释为布尔值:调用了attrs.getAttributeBooleanValue(....).

In this for-loop it gets the android:drawable, the various android:state_xxxx and custom app:xxxx attributes. All but the android:drawable attributes seem to be interpreted as booleans only: attrs.getAttributeBooleanValue(....) is called.

我认为这是答案,基于源代码:

I think this is the answer, based on the source code:

您只能向XML添加自定义布尔属性,而不能添加任何其他类型(包括枚举).

You can only add custom boolean attributes to your xml, not any other type (including enums).

第二季度:

我不确定为什么仅将状态专门设置为true才合并状态.我怀疑代码应该看起来像这样:

I'm not sure why the state is merged only if it is specifically set to true. I would suspect the code should have looked like this instead:

private static final int[] MAKE_DARK_BG_SET     = {  R.attr.make_dark_background };
private static final int[] NOT_MAKE_DARK_BG_SET = { -R.attr.make_dark_background };
....
....
@Override
protected int[] onCreateDrawableState(int extraSpace) {
    Log.i(TAG, "onCreateDrawableState()");
    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    mergeDrawableStates(drawableState, mMakeDarkBg? MAKE_DARK_BG_SET : NOT_MAKE_DARK_BG_SET);
    //mergeDrawableStates(drawableState, STR_ATTR_ID);
    return drawableState;
}

这篇关于Android:可以在可绘制选择器中使用字符串/枚举吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆