@ (Ted Hopp) ile gösterilen çözüm işe yarıyor, ancak biraz düzeltilmesi gerekiyor: seçicide, öğe durumları bir "app:" önekine ihtiyaç duyar, aksi takdirde şişirici ad alanını doğru bir şekilde tanımaz ve sessizce başarısız olur; en azından bana olan bu.
Burada tüm çözümü biraz daha ayrıntıyla birlikte bildirmeme izin verin:
Önce "res / values / attrs.xml" dosyasını oluşturun:
<?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>
Ardından özel sınıfınızı tanımlayın. Örneğin, "Button" sınıfından türetilmiş bir "FoodButton" sınıfı olabilir. Bir kurucu uygulamanız gerekecek; Şişirici tarafından kullanılan gibi görünen bunu uygulayın:
public FoodButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
Türetilmiş sınıfın üstünde:
private static final int[] STATE_FRIED = {R.attr.state_fried};
private static final int[] STATE_BAKED = {R.attr.state_baked};
Ayrıca, durum değişkenleriniz:
private boolean mIsFried = false;
private boolean mIsBaked = false;
Ve birkaç pasör:
public void setFried(boolean isFried) {mIsFried = isFried;}
public void setBaked(boolean isBaked) {mIsBaked = isBaked;}
Ardından "onCreateDrawableState" işlevini geçersiz kılın:
@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;
}
Son olarak, bu bulmacanın en hassas parçası; Widget'ınız için arka plan olarak kullanacağınız StateListDrawable'ı tanımlayan seçici. Bu "res / drawable / food_button.xml" dosyasıdır:
<?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>
Standart android durumlarında "android:" önekini kullanırdınız, oysa "app:" önekine dikkat edin. XML ad alanı, şişirici tarafından doğru bir yorumlama için çok önemlidir ve öznitelikleri eklediğiniz projenin türüne bağlıdır. Bu bir uygulamaysa, com.mydomain.mypackage yerine uygulamanızın gerçek paket adını yazın (uygulama adı hariçtir). Bir kitaplıksa, "http://schemas.android.com/apk/res-auto" kullanmanız gerekir (ve Araçlar R17 veya üzerini kullanıyor olmanız gerekir), aksi takdirde çalışma zamanı hataları alırsınız.
Birkaç not:
Görünüşe göre "renewDrawableState" işlevini çağırmanıza gerek yok, en azından çözüm benim durumumda olduğu gibi çalışıyor
Özel sınıfınızı bir düzen xml dosyasında kullanmak için, tam olarak nitelenmiş adı belirtmeniz gerekir (örn. Com.mydomain.mypackage.FoodButton)
Daha karmaşık durum kombinasyonlarını temsil etmek için, standart durumları (örn. Android: basılı, android: etkin, android: seçili) özel durumlarla karıştırabilirsiniz.