6

私は Android 開発の初心者で、その仕組みを理解するために小さなアプリを書いています。すべてが機能していますが、現時点では、カスタム ドローアブルの状態についてのポイントを得ることができません... サンプル コードで説明させてください。

これが私のattrs.xmlです。ここでは、ブール値である「oddMonth」という名前の属性を宣言しています。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DayView">
        <attr name="oddMonth" format="boolean"/>
    </declare-styleable>
</resources>

次に、カスタム ビューがあります。

<?xml version="1.0" encoding="utf-8"?>
<com.example.calendar.DayView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="90dp"
    android:background="@drawable/dayview_state" >
    <TextView android:id="@+id/day_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:paddingRight="3dp" />  
</com.example.calendar.DayView>

そこで、dayview_state.xml ファイルを参照する「android:background="@drawable/dayview_state"」という行を追加します。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:easycalendar="http://schemas.android.com/apk/res/com.example.calendar">

    <item easycalendar:oddMonth ="true" android:drawable="@drawable/customborder_odd" />
    <item easycalendar:oddMonth ="false" android:drawable="@drawable/customborder_even"/>

</selector>

これまでのところ...私が理解できることは.... attrs.xmlで定義された属性があります。この属性は、カスタム ビューの状態を表します。この属性のブール値によると、私のアプリは 2 つの異なる xml (ここでは重要ではありません) のいずれかをロードし、それぞれが異なるドローアブルを定義します。最後のステップは、カスタム クラスを作成することです。クラスからの抜粋に従います。

public class DayView extends RelativeLayout {
    private static final int[] STATE_ODD_MONTH = { R.attr.oddMonth };
    private boolean mOddmonth = true;

    public DayView(Context mContext, AttributeSet attrs) {
        super(mContext, attrs);
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mOddmonth) {
            final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            mergeDrawableStates(drawableState, STATE_ODD_MONTH);

            return drawableState;
        } else {
            return super.onCreateDrawableState(extraSpace);
        }
    }

    public boolean isOddMonth() {
        return mOddmonth;
    }

    public void setOddMonth(boolean oddMonth) {
        if (mOddmonth != oddMonth) {
            mOddmonth = oddMonth;

            refreshDrawableState();
        }
    }
}

わかりました...ここにプライベート変数 mOddMonth があり、getter と setter があります。このビューを他の場所でインフレートするために使用されるコンストラクター。別のプライベート変数:

private static final int[] STATE_ODD_MONTH = { R.attr.oddMonth };

これは、1 つの int 値のみで構成される配列であり、attrs.xml で定義された属性 oddMonth への参照です。そして継承されたメソッド:

@Override
    protected int[] onCreateDrawableState(int extraSpace) {
        if (mOddmonth) {
            final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
            mergeDrawableStates(drawableState, STATE_ODD_MONTH);

            return drawableState;
        } else {
            return super.onCreateDrawableState(extraSpace);
        }
    }

これは本当に「深く」理解することはできません...まあ、ローカル変数mOddMonthがtrueの場合は状態を追加し、そうでない場合は追加しないようです。だから...私のコードは、dayview_state.xmlを次のものに置き換えた場合にのみ機能します。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:easycalendar="http://schemas.android.com/apk/res/com.example.calendar">

    <item easycalendar:oddMonth ="true" android:drawable="@drawable/customborder_odd" />
    <item android:drawable="@drawable/customborder_even"/>

</selector>

このようにして、状態が存在する場合は最初のレイアウトがロードされ、それ以外の場合は 2 番目のレイアウトがロードされます。しかし、国家の価値についてはどうでしょうか? 私のコードのどこにも、この変数/属性の値を設定していません....どこが間違っていますか?

4

2 に答える 2

0

あなたは正しいです。AttributeSet 変数を使用して、コンストラクターでその値を割り当てる必要があります。

TypedArray values = context.obtainStyledAttributes(attrs, STATE_ODD_MONTH);
boolean isOddMonth = values.getBoolean(R.attr.oddMonth, false);
mOddmonth = isOddMonth;
values.recycle();

これでうまくいくと思います。私は通常、int[] をハードコーディングする代わりに、attrs.xml でdeclare-styleable タグを使用しますが、同じように機能するはずです。

于 2013-02-12T01:00:08.797 に答える