22

質問

Q1 : xml セレクターで動作するカスタム文字列/列挙型属性を取得できた人はいますか? [1] に従って動作するブール属性を取得しましたが、文字列属性は取得しませんでした。

編集:答えてくれてありがとう。現在、android はブール セレクターのみをサポートしています。理由については、受け入れられた回答を参照してください。

外観が 2 つの変数に依存する少し複雑なカスタム ボタンを実装する予定です。その他は、ブール属性 (true または false) と別のカテゴリのような属性 (多くの異なる値を持つ) です。私の計画は、ブール値と文字列 (または多分列挙型?) 属性を使用することです。ブール値と文字列属性を使用して xml セレクターで UI を定義できることを望んでいました。

Q2 : なぜ [1] onCreateDrawableState() でブール属性が true の場合にのみマージされるのですか?

これは私がテストしたものです。ブール属性は機能しますが、文字列は機能しません

: これは、xml セレクターで string/enum 属性が可能かどうかを確認するための単なるテスト アプリです。カスタム属性なしでボタンのテキストカラーを設定できることを知っています。

私のデモ アプリケーションでは、boolean 属性を使用してボタンの背景を暗い/明るいに設定し、string 属性を使用してテキストの色を {"red"、"green"、"blue"} のいずれかに設定します。属性はで定義されています/res/values/attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomButton">
        <attr name="make_dark_background" format="boolean" />
        <attr name="str_attr" format="string" />
    </declare-styleable>
</resources>

実現したいセレクターは次のとおりです。

@drawable/custom_button_background (動作します)

<?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.example.customstringattribute">

    <item app:make_dark_background="true" android:drawable="@color/dark" />
    <item android:drawable="@color/bright" />

</selector>

@color/custom_button_text_color (これは機能しません)

<selector 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.customstringattribute">

    <item app:str_attr="red" android:color="@color/red" />
    <item app:str_attr="green" android:color="@color/green" />
    <item app:str_attr="blue" android:color="@color/blue" />

    <item android:color="@color/grey" />

</selector>

カスタム ボタンの背景をブール セレクターに接続し、テキストの色を文字列セレクターに接続する方法を次に示します。

<com.example.customstringattribute.MyCustomButton
    ...
    android:background="@drawable/custom_button_background"
    android:textColor="@color/custom_button_text_color"
    ...
/>

init() メソッドで属性をロードする方法は次のとおりです。

private void init(AttributeSet attrs) {

    TypedArray a = getContext().obtainStyledAttributes(attrs,
            R.styleable.MyCustomButton);

        final int N = a.getIndexCount();
        for (int i = 0; i < N; ++i)
        {
            int attr = a.getIndex(i);
            switch (attr)
            {
                case R.styleable.MyCustomButton_str_attr:
                    mStrAttr = a.getString(attr);
                    break;
                case R.styleable.MyCustomButton_make_dark_background:
                    mMakeDarkBg  = a.getBoolean(attr, false);
                    break;
            }
        }
        a.recycle();
}

属性の int[] 配列があります

private static final int[] MAKE_DARK_BG_SET = { R.attr.make_dark_background };
private static final int[] STR_ATTR_ID = { R.attr.str_attr };

そして、これらの int[] 配列は描画可能な状態にマージされます

@Override
protected int[] onCreateDrawableState(int extraSpace) {
    Log.i(TAG, "onCreateDrawableState()");
    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    if(mMakeDarkBg){
        mergeDrawableStates(drawableState, MAKE_DARK_BG_SET);
    }
    mergeDrawableStates(drawableState, STR_ATTR_ID);
    return drawableState;
}

また、属性セッター メソッドに refreshDrawableState() があります。

public void setMakeDarkBg(boolean makeDarkBg) {
    if(mMakeDarkBg != makeDarkBg){
        mMakeDarkBg = makeDarkBg;
        refreshDrawableState();
    }
}

public void setStrAttr(String str) {
    if(mStrAttr != str){
        mStrAttr = str;
        refreshDrawableState();
    }
}

[1] :カスタム ボタン状態を追加する方法

4

3 に答える 3

14

Q1:

StateListDrawable.java のソースコードを開くとinflate、ドローアブル xml セレクターを読み取るメソッドで次のコードを見ることができます: https://android.googlesource.com/platform/frameworks/base/+/refs/heads /master/graphics/java/android/graphics/drawable/StateListDrawable.java

        ...

        for (i = 0; i < numAttrs; i++) {
            final int stateResId = attrs.getAttributeNameResource(i);
            if (stateResId == 0) break;
            if (stateResId == com.android.internal.R.attr.drawable) {
                drawableRes = attrs.getAttributeResourceValue(i, 0);
            } else {
                states[j++] = attrs.getAttributeBooleanValue(i, false)
                        ? stateResId
                        : -stateResId;
            }
        }
        ...

attrsの各<item>要素の属性です<selector>

この for ループではandroid:drawable、さまざまな属性android:state_xxxxとカスタムapp:xxxx属性を取得します。属性以外はすべてandroid:drawableブール値のみとして解釈されるようです:attrs.getAttributeBooleanValue(....)が呼び出されます。

ソースコードに基づいて、これが答えだと思います:

カスタムのブール属性のみを xml に追加できます。他のタイプ (列挙型を含む) は追加できません。

Q2:

明確にtrueに設定されている場合にのみ、状態がマージされる理由がわかりません。代わりに、コードは次のようになるはずだったと思います。

private static final int[] MAKE_DARK_BG_SET     = {  R.attr.make_dark_background };
private static final int[] NOT_MAKE_DARK_BG_SET = { -R.attr.make_dark_background };
....
....
@Override
protected int[] onCreateDrawableState(int extraSpace) {
    Log.i(TAG, "onCreateDrawableState()");
    final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    mergeDrawableStates(drawableState, mMakeDarkBg? MAKE_DARK_BG_SET : NOT_MAKE_DARK_BG_SET);
    //mergeDrawableStates(drawableState, STR_ATTR_ID);
    return drawableState;
}
于 2013-03-05T15:24:08.540 に答える
1

Q1:

私はこれを自分で試したことはありませんが、

フォルダに配置しようとし@color/custom_button_text_color.xmlましたか?drawable(念のため言っておきますが、Android のあちこちにフォルダ マジックが少しありますが、これについてはよくわかりません。)

Q2:

状態セットには 2 つの使用例があります。1 つは、ステートフルなドローアブルのセレクターをプログラムで明示的に宣言することです。この場合、セレクターの場合、属性が設定されていない場合にこのドローアブルを使用するように Android に指示できる必要があります。これを表現するために、否定された基準 (マイナス記号が前に付いている) を に含めることができます。int[]

これは、セレクター基準のコンテキストではほとんど言及されていませんが、ドローアブルの状態自体 (つまり、ドローアブルの状態の表現) については言及されていません。したがって、否定された状態 ID をセットに含めない場合は、間違いなく安全です。提供されている Android 実装にも含まれていません。

于 2013-03-05T11:30:38.967 に答える
0

申し訳ありませんが、xml でカスタム ドローアブルを作成することはできません: https://groups.google.com/d/msg/android-developers/glpdi0AdMzI/LpW4HGMB3VIJ

于 2013-02-26T23:00:40.553 に答える