web-dev-qa-db-ja.com

コードでattrs.xmlに作成された列挙型を取得する方法

Enum型のdeclare-styleable属性を持つカスタムビュー( here )を作成しました。 xmlで、カスタム属性の列挙型エントリの1つを選択できるようになりました。この値をプログラムで設定するメソッドを作成したいのですが、列挙型にアクセスできません。

attr.xml

_<declare-styleable name="IconView">
    <attr name="icon" format="enum">
        <enum name="enum_name_one" value="0"/>
        ....
        <enum name="enum_name_n" value="666"/>
   </attr>
</declare-styleable>     
_

layout.xml

_<com.xyz.views.IconView
    Android:id="@+id/heart_icon"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    app:icon="enum_name_x"/>
_

私が必要なものは次のようなものです:mCustomView.setIcon(R.id.enum_name_x);しかし、私は列挙型を見つけることができません。

92
Informatic0re

属性列挙型からJava列挙型を取得する自動化された方法はないようです-in Java指定した数値を取得できます-文字列(示されているように)XMLファイルで使用します。

ビューコンストラクタでこれを行うことができます:

TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.IconView,
                0, 0);

    // Gets you the 'value' number - 0 or 666 in your example
    if (a.hasValue(R.styleable.IconView_icon)) {
        int value = a.getInt(R.styleable.IconView_icon, 0));
    }

    a.recycle();
}

値を列挙型にしたい場合は、値をJava自身で列挙型にマッピングする必要があります。例えば:

private enum Format {
    enum_name_one(0), enum_name_n(666);
    int id;

    Format(int id) {
        this.id = id;
    }

    static Format fromId(int id) {
        for (Format f : values()) {
            if (f.id == id) return f;
        }
        throw new IllegalArgumentException();
    }
}

次に、最初のコードブロックで使用できます。

Format format = Format.fromId(a.getInt(R.styleable.IconView_icon, 0))); 

(この時点で例外をスローするのは良い考えではないかもしれませんが、おそらく賢明なデフォルト値を選択する方が良いでしょう)

89
Andy Mell

それは簡単です、それがどれほど簡単かを示すために、みんなに例を示しましょう:

attr.xml:

<declare-styleable name="MyMotionLayout">
    <attr name="motionOrientation" format="enum">
        <enum name="RIGHT_TO_LEFT" value="0"/>
        <enum name="LEFT_TO_RIGHT" value="1"/>
        <enum name="TOP_TO_BOTTOM" value="2"/>
        <enum name="BOTTOM_TO_TOP" value="3"/>
    </attr>
</declare-styleable>

カスタムレイアウト:

public enum Direction {RIGHT_TO_LEFT, LEFT_TO_RIGHT, TOP_TO_BOTTOM, BOTTOM_TO_TOP}
Direction direction;
...
    TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyMotionLayout);
    Direction direction = Direction.values()[ta.getInt(R.styleable.MyMotionLayout_motionOrientation,0)];

他の列挙変数と同じように方向を使用するようになりました。

16
steve moretz

まあ、正気のために。宣言されたスタイル設定で、Enum宣言と順序が同じであることを確認し、配列としてアクセスします。

TypedArray a = context.getTheme().obtainStyledAttributes(
                   attrs,
                   R.styleable.IconView,
                   0, 0);

int ordinal = a.getInt(R.styleable.IconView_icon, 0);

if (ordinal >= 0 && ordinal < MyEnum.values().length) {
      enumValue = MyEnum.values()[ordinal];
}
11
Dave Thomas

質問が投稿されてからしばらく経ちましたが、最近同じ問題が発生しました。 SquareのJavaPoetとbuild.gradleの一部を使用して、プロジェクトビルド時にattrs.xmlからJava enumクラスを自動的に作成する小さなものを一緒にハッキングしました。

https://github.com/afterecho/create_enum_from_xml に説明付きの小さなデモとreadmeがあります

それが役に立てば幸い。

3
Darren