web-dev-qa-db-fra.com

Comment obtenir une énumération créée dans attrs.xml en code

J'ai créé une vue personnalisée (find it here ) avec un attribut declare-styleable de type enum. En XML, je peux maintenant choisir l'une des entrées enum pour mon attribut personnalisé. Maintenant, je veux créer une méthode pour définir cette valeur par programme, mais je ne peux pas accéder à l'énumération.

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

Ce dont j'ai besoin, c'est quelque chose comme: mCustomView.setIcon(R.id.enum_name_x); Mais je ne peux pas trouver l'énum ou je ne sais même pas comment je peux obtenir l'énum ou les noms de l'énum.

92
Informatic0re

Il ne semble pas y avoir de moyen automatisé d’obtenir un Java enum à partir d’un attribut enum - in Java vous pouvez obtenir la valeur numérique que vous avez spécifiée - la chaîne est pour une utilisation dans les fichiers XML (comme vous le montrez).

Vous pouvez le faire dans votre constructeur de vues:

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 vous voulez la valeur dans une énumération, vous devez mapper la valeur dans un Java enum vous-même, par exemple:

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

Ensuite, dans le premier bloc de code, vous pouvez utiliser:

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

(bien que lancer une exception à ce stade ne soit pas une bonne idée, il vaut probablement mieux choisir une valeur par défaut raisonnable)

89
Andy Mell

C'est simple, montrons à tout le monde un exemple pour montrer à quel point c'est facile:

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>

Mise en page personnalisée:

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

utilisez maintenant la direction comme toute autre variable d’énumération.

16
steve moretz

Bien pour la santé mentale. Assurez-vous que vos ordinaux sont les mêmes dans votre style déclarable que dans votre déclaration Enum et accédez-y en tant que tableau.

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

Je sais que cela fait longtemps que la question n'a pas été publiée, mais j'ai eu le même problème récemment. J'ai piraté un petit quelque chose qui utilise JavaPoet de Square et des éléments du build.gradle qui crée automatiquement une classe Java enum à partir du attrs.xml sur la construction du projet.

Il y a une petite démo et un fichier lisez-moi avec une explication à l'adresse https://github.com/afterecho/create_enum_from_xml

J'espère que ça aide.

3
Darren