Рішення, вказане @ (Тед Хопп), працює, але потребує невеликої корекції: у селекторі для пункту пункту потрібен префікс "app:", інакше надувальник не розпізнає простір імен правильно, і вийде з ладу; принаймні, це те, що відбувається зі мною.
Дозвольте мені повідомити тут про все рішення, із деякими деталями:
Спочатку створіть файл "res / values / 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", похідний від класу "Кнопка". Вам доведеться реалізувати конструктор; реалізуйте цей, який, здається, той, який використовує надувальник:
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;
І пара сетерів:
public void setFried(boolean isFried) {mIsFried = isFried;}
public void setBaked(boolean isBaked) {mIsBaked = isBaked;}
Тоді перезазначте функцію "onCreateDravableState":
@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, який ви будете використовувати як фон для свого віджета. Це файл "res / dravable / 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>
Зверніть увагу на префікс "app:", тоді як при стандартних андроїдних станах ви використовували б префікс "android:". Простір імен XML має вирішальне значення для правильної інтерпретації інфлятора і залежить від типу проекту, в який ви додаєте атрибути. Якщо це програма, замініть com.mydomain.mypackage фактичною назвою пакета вашої програми (назва програми виключена). Якщо це бібліотека, ви повинні використовувати "http://schemas.android.com/apk/res-auto" (і використовувати Інструменти R17 або новіші версії), або ви отримаєте помилки під час виконання.
Пара приміток:
Здається, вам не потрібно викликати функцію "refreshDravableState", принаймні рішення добре працює, як і в моєму випадку
Щоб використовувати свій власний клас у файлі xml-макета, вам доведеться вказати повністю кваліфіковане ім’я (наприклад, com.mydomain.mypackage.FoodButton)
Ви можете використовувати стандартні стани (наприклад, android: натиснутий, android: увімкнено, android: вибрано) за допомогою спеціальних станів, щоб представити більш складні комбінації станів