@(Ted Hopp)で示される解決策は機能しますが、少し修正する必要があります。セレクターでは、アイテムの状態に「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>
次に、カスタムクラスを定義します。たとえば、「Button」クラスから派生した「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;}
次に、関数「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を定義するセレクター。これは "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>
「app:」接頭辞に注意してください。標準のAndroid状態では、接頭辞「android:」を使用します。XML名前空間は、インフレーターによる正しい解釈に不可欠であり、属性を追加するプロジェクトのタイプによって異なります。アプリケーションの場合は、com.mydomain.mypackageをアプリケーションの実際のパッケージ名(アプリケーション名を除く)に置き換えます。ライブラリの場合は、「http://schemas.android.com/apk/res-auto」を使用する必要があり(ツールR17以降を使用している場合)、ランタイムエラーが発生します。
いくつかのメモ:
「refreshDrawableState」関数を呼び出す必要がないようです。少なくとも、私の場合、ソリューションは問題なく機能します。
カスタムクラスをレイアウトxmlファイルで使用するには、完全修飾名を指定する必要があります(例:com.mydomain.mypackage.FoodButton)
より複雑な状態の組み合わせを表すために、カスタム状態と標準状態(例:android:pressed、android:enabled、android:selected)を組み合わせることができます。