La soluzione indicata da @ (Ted Hopp) funziona, ma necessita di una piccola correzione: nel selettore, gli stati degli elementi hanno bisogno di un prefisso "app:", altrimenti il gonfiatore non riconoscerà correttamente lo spazio dei nomi e fallirà silenziosamente; almeno questo è quello che mi succede.
Consentitemi di segnalare qui l'intera soluzione, con alcuni dettagli:
Innanzitutto, crea il file "res / valori / 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>
Quindi definisci la tua classe personalizzata. Ad esempio, può essere una classe "FoodButton", derivata dalla classe "Button". Dovrai implementare un costruttore; implementare questo, che sembra essere quello utilizzato dal gonfiatore:
public FoodButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
Oltre alla classe derivata:
private static final int[] STATE_FRIED = {R.attr.state_fried};
private static final int[] STATE_BAKED = {R.attr.state_baked};
Inoltre, le variabili di stato:
private boolean mIsFried = false;
private boolean mIsBaked = false;
E un paio di setter:
public void setFried(boolean isFried) {mIsFried = isFried;}
public void setBaked(boolean isBaked) {mIsBaked = isBaked;}
Quindi sovrascrivere la funzione "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;
}
Finalmente il pezzo più delicato di questo puzzle; il selettore che definisce StateListDrawable che utilizzerai come sfondo per il tuo widget. Questo è il file "res / drawable / 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>
Nota il prefisso "app:", mentre con gli stati Android standard avresti usato il prefisso "android:". Lo spazio dei nomi XML è cruciale per una corretta interpretazione da parte del gonfiatore e dipende dal tipo di progetto in cui si stanno aggiungendo gli attributi. Se si tratta di un'applicazione, sostituire com.mydomain.mypackage con il nome del pacchetto effettivo dell'applicazione (nome dell'applicazione escluso). Se si tratta di una libreria, è necessario utilizzare "http://schemas.android.com/apk/res-auto" (e utilizzare Strumenti R17 o successivi) o si otterranno errori di runtime.
Un paio di note:
Sembra che non sia necessario chiamare la funzione "refreshDrawableState", almeno la soluzione funziona bene così com'è, nel mio caso
Per utilizzare la tua classe personalizzata in un file xml di layout, dovrai specificare il nome completo (ad es. Com.mydomain.mypackage.FoodButton)
Puoi come weel confondere gli stati standard (es. Android: premuto, android: abilitato, android: selezionato) con stati personalizzati, al fine di rappresentare combinazioni di stati più complicate