Вопросы
Q1: Кто-нибудь смог получить настраиваемый атрибут string/enum, работающий в селекторах xml? Я получил логический атрибут, работающий с помощью [1], но не строкового атрибута.
EDIT: Спасибо за ответы. В настоящее время андроид поддерживает только логические селекторы. См. Принятый ответ по этой причине.
Я планирую реализовать небольшую сложную пользовательскую кнопку, внешний вид которой зависит от двух переменных. Другим будет логический атрибут (true или false) и другой атрибут категории (имеет много разных возможных значений). Мой план состоит в том, чтобы использовать атрибуты boolean и string (или, возможно, enum?). Я надеялся, что могу определить UI в селекторе xml с использованием логического и строкового атрибутов.
Q2. Почему в [1] onCreateDrawableState() логические атрибуты объединяются, только если они истинны?
Это то, что я тестировал, boolean атрибут работает, строка не
ПРИМЕЧАНИЕ. Это просто тестовое приложение, чтобы выяснить, возможен ли атрибут string/enum в селекторе xml. Я знаю, что я могу установить цвет текста кнопки без пользовательского атрибута.
В моем демонстрационном приложении я использую логический атрибут для установки фона кнопки для темного/яркого и строкового атрибута для установки цвета текста, одного из "красного", "зеленого", "синего" }. Атрибуты определены в /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;
}
У меня также есть refreshDrawableState() в моих методах настройки атрибутов:
public void setMakeDarkBg(boolean makeDarkBg) {
if(mMakeDarkBg != makeDarkBg){
mMakeDarkBg = makeDarkBg;
refreshDrawableState();
}
}
public void setStrAttr(String str) {
if(mStrAttr != str){
mStrAttr = str;
refreshDrawableState();
}
}