Решение, указанное компанией @ (Ted Hopp), работает, но нуждается в небольшой коррекции: в селекторе item требует префикса «app:», иначе надуватель не будет правильно распознавать пространство имен и будет терпеть неудачу; по крайней мере, это то, что происходит со мной.
Позвольте мне сообщить здесь все решения, еще с некоторыми деталями:
Во-первых, создать файл "Рез/значения/attrs.xml":
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="food">
<attr name="state_fried" format="boolean" />
<attr name="state_baked" format="boolean" />
</declare-styleable>
</resources>
Затем определите свой собственный класс. Например, это может быть класс «FoodButton», полученный из класса «Button». Вам нужно будет реализовать конструктор; реализовать этот, который, кажется, один используется Inflater:
public FoodButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
В верхней части производного класса:
private static final int[] STATE_FRIED = {R.attr.state_fried};
private static final int[] STATE_BAKED = {R.attr.state_baked};
Кроме того, ваши переменные состояния:
private boolean mIsFried = false;
private boolean mIsBaked = false;
И несколько сеттеров:
Затем переопределить функцию "onCreateDrawableState":
@Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
if (mIsFried) {
mergeDrawableStates(drawableState, STATE_FRIED);
}
if (mIsBaked) {
mergeDrawableStates(drawableState, STATE_BAKED);
}
return drawableState;
}
Наконец, самая деликатная часть этой головоломки; селектор, определяющий StateListDrawable, который вы будете использовать в качестве фона для вашего виджета. Это файл «Рез/рисуем/food_button.xml»:
<?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.mydomain.mypackage">
<item
app:state_baked="true"
app:state_fried="false"
android:drawable="@drawable/item_baked" />
<item
app:state_baked="false"
app:state_fried="true"
android:drawable="@drawable/item_fried" />
<item
app:state_baked="true"
app:state_fried="true"
android:drawable="@drawable/item_overcooked" />
<item
app:state_baked="false"
app:state_fried="false"
android:drawable="@drawable/item_raw" />
</selector>
Обратите внимание на «приложение:» префикс, в то время как со стандартными андроида состояниями вы бы использовали приставку «андроид:». Пространство имен XML имеет решающее значение для правильной интерпретации надувателем и зависит от типа проекта, в котором вы добавляете атрибуты. Если это приложение, замените com.mydomain.mypackage с фактическим именем вашего приложения (исключение имени приложения). Если это библиотека, вы должны использовать «http://schemas.android.com/apk/res-auto» (и использовать инструменты R17 или новее), или вы получите ошибки времени выполнения.
Несколько примечаний:
Кажется, вам не нужно вызывать функцию «refreshDrawableState», по крайней мере, решение хорошо работает как в моем случае
Для того, чтобы использовать свой собственный класс в XML-файле макета, вам нужно будет указать полное имя (например, com.mydomain.mypackage.FoodButton)
Вы можете, как Weel потасовка стандартные состояния (например, андроид: нажимается, андроид: включен, андроид: выбран) с пользовательскими состояниями, для того, чтобы представить более сложные государственные комбинации
Я хотел получить дополнительные состояния для вида EditText, чтобы определить, когда два поля для паролей соответствуют маленькой галочке. – schwiz 2010-12-23 22:07:53