Q1 :有没有人设法在xml选择器中使用自定义字符串/枚举属性?我通过以下[1]获得了一个布尔属性,但不是字符串属性。
编辑:谢谢你的回答。目前android仅支持布尔选择器。请参阅接受的答案。我打算实现一个复杂的自定义按钮,其外观取决于两个变量。其他将是布尔属性(true或false)和另一个类别属性(具有许多不同的可能值)。我的计划是使用布尔和字符串(或枚举?)属性。我希望我可以使用boolean和string属性在xml选择器中定义UI。
Q2 :为什么在[1]中onCreateDrawableState(),布尔属性只有在它们为真时才合并?
注意:这只是一个测试应用程序,用于确定xml选择器中是否可以使用string / enum属性。我知道我可以在没有自定义属性的情况下设置按钮的文本颜色。
在我的演示应用程序中,我使用布尔属性将按钮背景设置为dark / bright,将string属性设置为设置文本颜色,{“red”,“green”,“blue”}之一。属性在/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>
以下是我想要实现的选择器:
@ drawable / custom_button_background(有效)
<?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(不起作用)
<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>
以下是自定义按钮背景如何连接到布尔选择器,文本颜色连接到字符串选择器。
<com.example.customstringattribute.MyCustomButton
...
android:background="@drawable/custom_button_background"
android:textColor="@color/custom_button_text_color"
...
/>
以下是init()方法中如何加载属性:
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 []数组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 []数组合并为可绘制状态
@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;
}
我的属性setter方法中也有refreshDrawableState():
public void setMakeDarkBg(boolean makeDarkBg) {
if(mMakeDarkBg != makeDarkBg){
mMakeDarkBg = makeDarkBg;
refreshDrawableState();
}
}
public void setStrAttr(String str) {
if(mStrAttr != str){
mStrAttr = str;
refreshDrawableState();
}
}
答案 0 :(得分:10)
<强> Q1:强>
当您打开StateListDrawable.java的源代码时,您可以在inflate
方法中看到这段代码,它读取了可绘制的xml选择器:
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
是<item>
中每个<selector>
元素的属性。
在此for循环中,它获取android:drawable
,各种android:state_xxxx
和自定义app:xxxx
属性。除了android:drawable
属性之外的所有属性似乎都只被解释为布尔值:attrs.getAttributeBooleanValue(....)
被调用。
我认为这是答案,基于源代码:
您只能将自定义布尔属性添加到xml,而不是任何其他类型(包括枚举)。
<强> Q2:强>
我不确定为什么只有在专门设置为true时才合并状态。我怀疑代码应该是这样的:
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;
}
答案 1 :(得分:1)
Q1:
我自己没试过,但是:
您是否尝试将@color/custom_button_text_color.xml
放入drawable
文件夹? (可以肯定的是,Android中存在一些文件夹魔法,我不确定这个。)
Q2:
状态集有两种用例。一种是以编程方式明确声明有状态drawable的选择器。在这种情况下,对于选择器,如果属性不设置,则需要能够告诉Android 使用此drawable。为了表达这一点,您可以在int[]
中包含否定的标准(前面带有减号)。
虽然在选择标准的上下文中几乎没有提到过,但是对于可绘制状态本身(也就是drawable状态的表示),它从未被提及过。因此,如果不在集合中包含否定状态ID,那么肯定是安全的;提供的Android实现也不包括它们。
答案 2 :(得分:0)
抱歉,您无法在xml中创建自定义drawable: https://groups.google.com/d/msg/android-developers/glpdi0AdMzI/LpW4HGMB3VIJ