Hier ist diese Frage: Definieren von benutzerdefinierten Attributen mit einigen Informationen, aber nicht viel.
Und dieser Beitrag . Es hat gute Informationen über Flaggen und Aufzählungen:
Benutzerdefinierte XML-Attributflags
Flags sind spezielle Attributtypen, da sie nur eine sehr kleine Teilmenge von Werten zulassen, nämlich diejenigen, die unter dem Attribut-Tag definiert sind. Flags werden durch ein Attribut "name" und ein Attribut "value" angegeben. Die Namen müssen innerhalb dieses Attributtyps eindeutig sein, die Werte jedoch nicht. Dies ist der Grund, warum wir während der Entwicklung der Android-Plattform "fill_parent" und "match_parent" hatten, die beide demselben Verhalten zugeordnet waren. Ihre Werte waren identisch.
Das Namensattribut wird dem Namen zugeordnet, der an der Wertstelle im Layout-XML verwendet wird, und erfordert kein Namespace-Präfix. Daher habe ich für den obigen "tilingMode" "center" als Attributwert gewählt. Ich hätte genauso gut "gestreckt" oder "wiederholen" wählen können, aber sonst nichts. Es wäre nicht einmal erlaubt gewesen, die tatsächlichen Werte zu ersetzen.
Das value-Attribut muss eine Ganzzahl sein. Die Wahl zwischen hexadezimaler oder standardmäßiger Zifferndarstellung liegt bei Ihnen. Es gibt einige Stellen im Android-Code, an denen beide verwendet werden, und der Android-Compiler akzeptiert diese auch gerne.
Benutzerdefinierte XML-Attribut-Aufzählungen
Aufzählungen werden fast identisch wie Flags mit einer Bestimmung verwendet. Sie können austauschbar mit ganzen Zahlen verwendet werden. Unter der Haube werden Aufzählungen und Ganzzahlen demselben Datentyp zugeordnet, nämlich einer Ganzzahl. Wenn Enums in der Attributdefinition mit Ganzzahlen angezeigt werden, verhindern sie „magische Zahlen“, die immer schlecht sind. Aus diesem Grund können Sie ein "android: layout_width" mit einer Dimension, einer Ganzzahl oder einer benannten Zeichenfolge "fill_parent" haben.
Nehmen wir an, ich erstelle ein benutzerdefiniertes Attribut mit dem Namen "layout_scroll_height", das entweder eine Ganzzahl oder eine Zeichenfolge "scroll_to_top" akzeptiert. Dazu würde ich ein Formatattribut "integer" hinzufügen und dem mit der Aufzählung folgen:
<attr name="layout_scroll_height" format="integer">
<enum name="scroll_to_top" value="-1"/>
</attr>
Die einzige Bedingung bei der Verwendung von Enums auf diese Weise ist, dass ein Entwickler, der Ihre benutzerdefinierte Ansicht verwendet, den Wert "-1" absichtlich in die Layoutparameter einfügen kann. Dies würde die Sonderfalllogik von "scroll_to_top" auslösen. Solch ein unerwartetes (oder erwartetes) Verhalten könnte Ihre Bibliothek schnell in den Stapel "Legacy-Code" verschieben, wenn die Enum-Werte schlecht ausgewählt würden.
Aus meiner Sicht sind die tatsächlichen Werte, die Sie einem Attribut in der Realität hinzufügen können, durch das begrenzt, was Sie daraus erhalten können. Weitere Hinweise finden Sie in der AttributeSet
Klassenreferenz hier .
Sie können erhalten:
- Boolesche Werte (
getAttributeBooleanValue
),
- schwimmt (
getAttributeFloatValue
),
- ints (
getAttributeIntValue
),
- Ints (as
getAttributeUnsignedIntValue
),
- und Strings (
getAttributeValue
)
enum
und findenflag
.Die Antwort von @Aleadam ist sehr hilfreich, aber imho lässt es einen großen Unterschied zwischen
enum
und ausflag
. Ersteres soll einen und nur einen Wert auswählen, wenn wir das entsprechende Attribut für eine Ansicht zuweisen. Die Werte des letzteren können jedoch mit dem bitweisen ODER-Operator kombiniert werden.Ein Beispiel in
res/values/attr.xml
<!-- declare myenum attribute --> <attr name="myenum"> <enum name="zero" value="0" /> <enum name="one" value="1" /> <enum name="two" value="2" /> <enum name="three" value="3" /> </attr> <!-- declare myflags attribute --> <attr name="myflags"> <flag name="one" value="1" /> <flag name="two" value="2" /> <flag name="four" value="4" /> <flag name="eight" value="8" /> </attr> <!-- declare our custom widget to be styleable by these attributes --> <declare-styleable name="com.example.MyWidget"> <attr name="myenum" /> <attr name="myflags" /> </declare-styleable>
In können
res/layout/mylayout.xml
wir jetzt tun<com.example.MyWidget myenum="two" myflags="one|two" ... />
Eine Aufzählung wählt also einen ihrer möglichen Werte aus, während Flags kombiniert werden können. Die numerischen Werte sollten diesen Unterschied widerspiegeln. In der Regel soll die Sequenz
0,1,2,3,...
für Aufzählungen (z. B. als Array-Indizes) und Flags verwendet werden,1,2,4,8,...
damit sie unabhängig voneinander hinzugefügt oder entfernt werden können. Verwenden Sie dazu bitweises ODER|
, um Flags zu kombinieren.Wir könnten explizit "Meta-Flags" mit Werten definieren, die keine Zweierpotenz sind, und so eine Art Kurzform für gängige Kombinationen einführen. Zum Beispiel, wenn wir dies in unsere
myflags
Erklärung aufgenommen hätten<flag name="three" value="3" />
dann hätten wir
myflags="three"
stattdessenmyflags="one|two"
für völlig identische Ergebnisse schreiben können wie3 == 1|2
.Persönlich schließe ich immer gerne ein
<flag name="none" value="0" /> <!-- or "normal, "regular", and so on --> <flag name="all" value="15" /> <!-- 15 == 1|2|4|8 -->
Dadurch kann ich alle Flags gleichzeitig deaktivieren oder setzen.
Subtiler kann es sein, dass ein Flag von einem anderen impliziert wird. Nehmen wir in unserem Beispiel an, dass das
eight
gesetzte Flag das Setzen desfour
Flags erzwingen sollte (sofern dies nicht bereits geschehen ist). Wir könnten dann neu definieren,eight
um sozusagen diefour
Flagge vorab einzuschließen.<flag name="eight" value="12" /> <!-- 12 == 8|4 -->
Wenn Sie die Attribute in einem Bibliotheksprojekt deklarieren, sie aber in Layouts eines anderen Projekts anwenden möchten (abhängig von der Bibliothek), müssen Sie ein Namespace-Präfix verwenden, das Sie im XML-Stammelement binden müssen. Z.B,
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:auto="http://schemas.android.com/apk/res-auto" ... > <com.example.MyWidget auto:myenum="two" auto:myflags="one|two" ... /> </RelativeLayout>
quelle