Как получить перечисление, которое создается в attrs.xml в коде

Я создал собственный вид (найдите его здесь) с объявленным стилем атрибута типа enum. В xml теперь я могу выбрать одну из записей enum для своего пользовательского атрибута. Теперь я хочу создать метод для установки этого значения программно, но я не могу получить доступ к перечислению.

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); Но я не могу найти перечисление, или я даже понятия не имею, как я могу получить перечисление или имена перечисления.

Ответ 1

Кажется, нет автоматизированного способа получения перечня Java из перечисления атрибутов - на 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))); 

(хотя выброс исключения в этот момент может быть не очень хорошей идеей, возможно, лучше выбрать разумное значение по умолчанию)

Ответ 2

Хорошо для сани. Убедитесь, что ваши ординалы одинаковы в объявленном стиле, как в объявлении 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

Это просто, давайте покажем всем пример, чтобы показать, насколько это просто:

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

Теперь используйте направление как любую другую переменную перечисления.

Ответ 4

Я знаю, что прошло некоторое время, так как вопрос был опубликован, но у меня была такая же проблема в последнее время. Я взломал кое-что вместе, которое использует Square JavaPoet и некоторые вещи в build.gradle, который автоматически создает класс enum Java из attrs.xml при сборке проекта.

Там небольшая демонстрация и чтение с объяснением в https://github.com/afterecho/create_enum_from_xml

Надеюсь, что это поможет.