코드에서 attrs.xml에 생성 된 enum을 얻는 방법


108

enum 유형의 선언 스타일 속성을 사용 하여 사용자 정의보기 ( 여기에서 찾기 )를 만들었습니다 . xml에서 이제 사용자 지정 속성에 대한 열거 형 항목 중 하나를 선택할 수 있습니다. 이제이 값을 프로그래밍 방식으로 설정하는 메서드를 만들고 싶지만 열거 형에 액세스 할 수 없습니다.

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); 그러나 열거 형을 찾을 수 없거나 열거 형 또는 열거 형의 이름을 어떻게 얻을 수 있는지조차 모릅니다.

답변:


100

속성 enum에서 Java enum을 가져 오는 자동화 된 방법이없는 것 같습니다. 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))); 

(이 시점에서 예외를 던지는 것은 좋은 생각이 아닐 수 있지만 합리적인 기본값을 선택하는 것이 더 낫습니다)


38

간단합니다. 얼마나 쉬운 지 보여주기 위해 모두에게 예제를 보여 드리겠습니다.

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)];

이제 다른 열거 형 변수처럼 방향을 사용합니다.


결론적으로 다음을 사용하여 Enum attr : TypedArray.getInt (R.styleable.name_your_define, defaultValue)
CalvinChe

@CalvinChe ,,이 돌아갑니다 int. Steve Moretz가 가지고 있습니다. 안보여서 멍청 하지만 새벽 4시 30 분 입니다. 잠자리에들 시간 ...
n00dles

네, 그렇게 간단합니다. 대답은 단지 그것을 더 잘 설명하기위한 예일뿐입니다.
스티브 모 레츠

2
그러나 이것은 기호에 대한 두 개의 병렬 정의를 만듭니다. 이것은 정의가 동일한 경우에만 작동합니다. 즉, 깨지기 쉽습니다. OP는 XML에서 생성 된 열거 형에 대한 코드 액세스를 예상했습니다. 그것은 가능할 것 같습니다.
Steve White

@SteveWhite xml에 대한 액세스 권한이 없기 때문에 자동화 할 수있는 방법이 없으며 하나의 정의에 의존하도록 할 수있는 방법이 없습니다. 이것은이를 달성하는 가장 깨끗한 (가능한) 방법입니다. xml을 구문 분석하고 다음과 같은 방식으로 액세스 할 수있는 경우 위대 할 수는 있지만 할 수는 없습니다. (코드에서 할 수는 없지만 xml을 읽는 플러그인을 작성하고 Java에 값을 추출하여 동기화되도록 할 수 있으므로 깨지기 쉽지 않습니다. 자동화되어 있기 때문입니다.)
steve moretz

13

제정신을 위해서. 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];
}

3
여기서 열거 형 서수에 의존하는 것은 신뢰할 수없는 코드를 생성 할 운명이라고 생각합니다. 하나는 업데이트되고 다른 하나는 업데이트되지 않으면 문제가 발생합니다.
tir38

1
그래서 더 나은 방법은 무엇입니까?
Jonathan

6

kotlin으로 작성된 솔루션을 추가하겠습니다. 인라인 확장 기능 추가 :

inline fun <reified T : Enum<T>> TypedArray.getEnum(index: Int, default: T) =
    getInt(index, -1).let { if (it >= 0) enumValues<T>()[it] else default 
}

이제 열거 형을 얻는 것은 간단합니다.

val a: TypedArray = obtainStyledAttributes(...)
val yourEnum: YourEnum = a.getEnum(R.styleable.YourView_someAttr, YourEnum.DEFAULT)
a.recycle()

4

질문이 게시 된 지 오래되었지만 최근에 같은 문제가 발생했습니다. Square의 JavaPoet과 프로젝트 빌드시 attrs.xml에서 Java enum 클래스를 자동으로 생성하는 build.gradle의 일부 항목을 함께 사용하는 것을 해킹했습니다.

https://github.com/afterecho/create_enum_from_xml에 설명이있는 약간의 데모와 추가 정보가 있습니다.

도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.