Android: Можно ли использовать string / enum в drawable selector?

Вопросов

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(); } } 

[1]: Как добавить пользовательское состояние кнопки

Q1:

Когда вы открываете исходный код StateListDrawable.java, вы можете увидеть этот фрагмент кода в методе inflate который читает переносимый селектор xml: https://android.googlesource.com/platform/frameworks/base/+/refs/ головки / мастер / графика / Java / Android / графика / рисуем / 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-loop он получает android:drawable , различные android:state_xxxx и пользовательские app: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; } 

Q1:

Я не пробовал это сам, но:

Вы пытались разместить свой @color/custom_button_text_color.xml в @color/custom_button_text_color.xml папке? (Чтобы быть уверенным, в Android есть немного волшебства папок, и я не уверен в этом.)

Q2:

Для наборов состояний существует два варианта использования. Один из них заключается в том, чтобы явным образом объявлять селекторы для программных сокращений с учетом состояния. В этом случае, для селекторов, вы должны иметь возможность сказать Android, чтобы использовать эту возможность, если атрибут не установлен. Чтобы выразить это, вы можете включить отрицательные критерии (которым предшествует знак минус) в int[] .

Хотя это нигде не упоминается нигде в контексте критериев выбора, он никогда не упоминается для самопроизвольных состояний (также как представление состояния drawable). Таким образом, один из них определенно находится в безопасном месте, если в набор не включены отрицаемые идентификаторы состояний; Предоставляемые приложения Android также не включают их.

К сожалению, вы не можете создавать пользовательские чертежи в xml: https://groups.google.com/d/msg/android-developers/glpdi0AdMzI/LpW4HGMB3VIJ