Die durch @ (Ted Hopp) angegebene Lösung funktioniert, muss jedoch etwas korrigiert werden: In der Auswahl benötigen die Elementzustände ein Präfix "app:", da der Inflater den Namespace sonst nicht richtig erkennt und stillschweigend fehlschlägt. Zumindest passiert mir das.
Gestatten Sie mir, hier die gesamte Lösung mit einigen weiteren Details zu melden:
Erstellen Sie zunächst die Datei "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>
Definieren Sie dann Ihre benutzerdefinierte Klasse. Beispielsweise kann es sich um eine Klasse "FoodButton" handeln, die von der Klasse "Button" abgeleitet ist. Sie müssen einen Konstruktor implementieren. Implementieren Sie dieses, das vom Inflater verwendet zu werden scheint:
public FoodButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
Über der abgeleiteten Klasse:
private static final int[] STATE_FRIED = {R.attr.state_fried};
private static final int[] STATE_BAKED = {R.attr.state_baked};
Auch Ihre Zustandsvariablen:
private boolean mIsFried = false;
private boolean mIsBaked = false;
Und ein paar Setter:
public void setFried(boolean isFried) {mIsFried = isFried;}
public void setBaked(boolean isBaked) {mIsBaked = isBaked;}
Überschreiben Sie dann die Funktion "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;
}
Schließlich das heikelste Stück dieses Puzzles; Der Selektor, der die StateListDrawable definiert, die Sie als Hintergrund für Ihr Widget verwenden. Dies ist die Datei "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>
Beachten Sie das Präfix "app:", während Sie bei Standard-Android-Status das Präfix "android:" verwendet hätten. Der XML-Namespace ist entscheidend für eine korrekte Interpretation durch den Inflater und hängt von der Art des Projekts ab, in dem Sie Attribute hinzufügen. Wenn es sich um eine Anwendung handelt, ersetzen Sie com.mydomain.mypackage durch den tatsächlichen Paketnamen Ihrer Anwendung (Anwendungsname ausgeschlossen). Wenn es sich um eine Bibliothek handelt, müssen Sie "http://schemas.android.com/apk/res-auto" verwenden (und Tools R17 oder höher verwenden). Andernfalls werden Laufzeitfehler angezeigt.
Ein paar Anmerkungen:
Es scheint, dass Sie die Funktion "refreshDrawableState" nicht aufrufen müssen, zumindest funktioniert die Lösung in meinem Fall so wie sie ist
Um Ihre benutzerdefinierte Klasse in einer Layout-XML-Datei verwenden zu können, müssen Sie den vollständig qualifizierten Namen angeben (z. B. com.mydomain.mypackage.FoodButton).
Sie können Standardzustände (z. B. Android: gedrückt, Android: aktiviert, Android: ausgewählt) mit benutzerdefinierten Zuständen verwechseln, um kompliziertere Zustandskombinationen darzustellen