Frage Wie man eine Enumeration erhält, die in attrs.xml im Code erstellt wird


Ich habe eine benutzerdefinierte Ansicht erstellt (finde sie Hier) mit einem deklarationsfähigen Attribut vom Typ enum. In XML kann ich nun einen der Enum-Einträge für mein benutzerdefiniertes Attribut auswählen. Jetzt möchte ich eine Methode erstellen, um diesen Wert programmgesteuert festzulegen, aber ich kann nicht auf die Enumeration zugreifen.

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

Was ich brauche ist etwas wie: mCustomView.setIcon(R.id.enum_name_x); Aber ich kann das Enum nicht finden oder ich habe überhaupt keine Ahnung, wie ich das Enum oder die Namen des Enums bekommen kann.


75
2017-08-22 13:57


Ursprung


Antworten:


Es scheint keinen automatisierten Weg zu geben, eine Java-Enumeration von einer Attribut-Enumeration zu erhalten - in Java kann man den angegebenen numerischen Wert erhalten - die Zeichenkette wird (wie Sie sehen) in XML-Dateien verwendet.

Sie könnten dies in Ihrem View-Konstruktor tun:

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

Wenn Sie den Wert in eine Enumeration aufnehmen möchten, müssen Sie den Wert entweder selbst in eine Java-Enumeration mappen, z.

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

Dann könnten Sie im ersten Codeblock verwenden:

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

(Obwohl das Auslösen einer Ausnahme zu diesem Zeitpunkt keine gute Idee ist, ist es wahrscheinlich besser, einen vernünftigen Standardwert zu wählen)


74
2017-09-24 20:58



Nun, um der Vernunft willen. Stellen Sie sicher, dass Ihre Ordinalzahlen in Ihrer Deklaration deklariert sind, wie in Ihrer Enum-Deklaration, und greifen Sie darauf als Array zu.

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



Ich weiß, dass es eine Weile her ist, seit die Frage gestellt wurde, aber ich hatte in letzter Zeit das gleiche Problem. Ich habe ein kleines Ding zusammengehackt, das Square's JavaPoet benutzt, und ein paar Sachen in build.gradle, die automatisch eine Java-Enum-Klasse aus der attrs.xml beim Projektaufbau erstellen.

Es gibt eine kleine Demo und eine Readme mit einer Erklärung bei https://github.com/afterecho/create_enum_from_xml

Ich hoffe es hilft.


2
2018-06-10 21:56