Pregunta Cómo obtener una enumeración que se crea en attrs.xml en el código


Creé una vista personalizada (encuéntrala aquí) con un atributo declare-styleable de tipo enum. En xml, ahora puedo elegir una de las entradas enum para mi atributo personalizado. Ahora quiero crear un método para establecer este valor programáticamente, pero no puedo acceder a la enumeración.

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"/>

Lo que necesito es algo así como: mCustomView.setIcon(R.id.enum_name_x); Pero no puedo encontrar la enumeración o incluso no tengo idea de cómo puedo obtener la enumeración o los nombres de la enumeración.


75
2017-08-22 13:57


origen


Respuestas:


No parece haber una forma automática de obtener una enumeración de Java a partir de un atributo enum; en Java puede obtener el valor numérico que especificó; la cadena se utiliza en archivos XML (como se muestra).

Podrías hacer esto en tu constructor de vista:

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();
}

Si desea que el valor se convierta en una enumeración, deberá asignar el valor en una enumeración Java usted mismo, por ejemplo:

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();
    }
}

Luego, en el primer bloque de código, podrías usar:

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

(aunque lanzar una excepción en este punto puede no ser una gran idea, probablemente sea mejor elegir un valor predeterminado razonable)


74
2017-09-24 20:58



Bueno, por el bien de la salud. Asegúrate de que tus ordinales sean los mismos en tu styleable declarado que en tu declaración de Enum y accede a ellos como una matriz.

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

9
2018-03-04 21:52



Sé que ha pasado un tiempo desde que se publicó la pregunta, pero tuve el mismo problema recientemente. He pirateado algo juntos que usa el JavaPoet de Square y algunas cosas en el build.gradle que crea automáticamente una clase enum de Java desde el attrs.xml en la construcción del proyecto.

Hay una pequeña demostración y un archivo Léame con una explicación de https://github.com/afterecho/create_enum_from_xml

Espero eso ayude.


2
2018-06-10 21:56