77 votes

Déclarant styleable attributs Android

Il y a peu de documentation sur l' declare-styleable balise qui nous permet de déclarer des styles personnalisés pour les composants. J'ai trouvé cette liste de valeurs valides pour l' format attribut de l' attr balise. Alors que c'est gentil comme il va, il n'explique pas comment utiliser certaines de ces valeurs. La navigation attr.xml (la source Android pour les attributs standard), j'ai découvert que vous pouvez faire des choses comme:

<!-- The most prominent text color.  -->
<attr name="textColorPrimary" format="reference|color" />

L' format attribut peut évidemment être réglé à une combinaison de valeurs. Sans doute l' format attribut permet à l'analyseur d'interpréter un style réel valeur. Puis j'ai découvert ce dans attr.xml:

<!-- Default text typeface. -->
<attr name="typeface">
    <enum name="normal" value="0" />
    <enum name="sans" value="1" />
    <enum name="serif" value="2" />
    <enum name="monospace" value="3" />
</attr>

<!-- Default text typeface style. -->
<attr name="textStyle">
    <flag name="normal" value="0" />
    <flag name="bold" value="1" />
    <flag name="italic" value="2" />
</attr>

Ces deux semblent déclarer un ensemble de valeurs autorisées pour l'indication du style.

J'ai donc deux questions:

  1. Quelle est la différence entre un attribut de style qui peut prendre un ensemble de enum valeurs et qui peut prendre un ensemble de flag valeurs?
  2. Quelqu'un sait-il à une meilleure documentation pour combien de declare-styleable travaux (autres que de l'ingénierie inverse le code source Android)?

70voto

Aleadam Points 25433

Il y a cette question ici: la Définition de la coutume attrs avec quelques infos, mais pas beaucoup.

Et ce post . Il a de bonnes infos sur les drapeaux et les énumérations:

XML personnalisé indicateurs d'Attribut

Les drapeaux sont en spécial les types d'attribut dans qu'ils sont autorisés seulement un très petit sous-ensemble de valeurs, à savoir ceux qui sont définies sous la attribut de la balise. Les drapeaux sont spécifiées par un attribut "name" et une "valeur" attribut. Les noms sont tenus de être unique au sein de ce type d'attribut mais les valeurs ne doivent pas être. C'est la raison qu'au cours de l'évolution de la plate-forme Android nous avons eu "fill_parent" et "match_parent" les deux la cartographie pour le même comportement. Leur les valeurs sont identiques.

L'attribut name correspond au nom utilisé dans la valeur place au sein de l' mise en page XML et ne nécessite pas de préfixe d'espace de noms. Ainsi, pour l' "tilingMode" ci-dessus, j'ai choisi "center" comme la valeur de l'attribut. Je pourrais avoir tout aussi facilement choisi "tendu" ou "répéter" mais rien d'autre. Pas même en remplaçant dans les valeurs réelles aurait été autorisé.

La valeur de l'attribut doit être un entier. Le choix de l'hexadécimal ou standard chiffre représentation est pour vous. Il ya quelques endroits à l'intérieur le code Android où les deux sont utilisés et le Android compilateur est heureux de accepter soit.

Personnalisé Attribut XML Enums

Les énumérations sont utilisés dans presque identique manière que les drapeaux avec une disposition, ils peuvent être utilisés de façon interchangeable avec les nombres entiers. Sous le capot, les Énumérations et Les entiers sont mappés sur les mêmes données type, à savoir un nombre Entier. Lorsque figurant dans la définition d'attribut avec les Entiers, les Énumérations servent à prévenir "nombres magiques" qui sont toujours mauvais. C'est pourquoi vous pouvez avoir un "android:layout_width" avec une dimension, un entier ou une chaîne nommée "fill_parent."

Pour mettre cela en contexte, nous allons supposons que je crée un custom attribut appelé "layout_scroll_height" qui accepte soit un entier ou une chaîne de caractères "scroll_to_top." Pour ce faire, je voudrais ajouter une "integer" attribut de format et de suivre qu'avec l'enum:

<attr name="layout_scroll_height" format="integer">  
    <enum name="scroll_to_top" value="-1"/> 
</attr>

L'une des stipulations lors de l'utilisation des Énumérations de cette manière, c'est qu'un développeur à l'aide de votre Vue personnalisée pourrait dessein de placer la valeur "-1" dans les paramètres de mise en page. Ce serait déclencher le cas particulier de la logique de "scroll_to_top." Ces imprévus (ou attendu) comportement pourrait rapidement reléguer votre bibliothèque à la "héritage code" tas si les valeurs Enum ont été choisis mal.


Comme je le vois, les valeurs réelles, vous pouvez ajouter dans la réalité d'un attribut est limité par ce que vous pouvez obtenir à partir de. Vérifier l' AttributeSet classe de référence ici pour plus de conseils.

Vous pouvez obtenir:

  • les booléens (getAttributeBooleanValue),
  • flotteurs (getAttributeFloatValue),
  • ints (getAttributeIntValue),
  • ints ( getAttributeUnsignedIntValue),
  • et les chaînes de caractères (getAttributeValue)

68voto

Rad Haring Points 140

@Aleadam 's réponse est très utile, mais à mon humble avis, il omet de souligner une différence importante entre l' enum et flag. Le premier est destiné pour nous d'en choisir une, et une seule valeur lorsque nous attribuer l'attribut correspondant pour certains. Les dernières valeurs peuvent être combinées, cependant, à l'aide de l'opérateur or.

Un exemple, en 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>

En res/layout/mylayout.xml nous pouvons maintenant faire

<com.example.MyWidget
    myenum="two"
    myflags="one|two"
    ... />

Donc un enum permet de sélectionner l'un de ses valeurs possibles, tandis que les indicateurs peuvent être combinés. Les valeurs numériques devrait tenir compte de cette différence, en général, vous aurez envie de la séquence d'aller 0,1,2,3,... pour les énumérations (pour être utilisés comme indices de tableau, par exemple) et des drapeaux pour aller de l' 1,2,4,8,... , de sorte qu'ils peuvent être indépendamment ajouté ou supprimé, l'aide OU binaire"/" | de combiner les drapeaux.

Nous pourrions définir explicitement les "méta-drapeaux" avec des valeurs qui ne sont pas une puissance de 2, et donc d'introduire une sorte d'abréviation pour la commune de combinaisons. Par exemple, si l'on avait inclus dans notre myflags déclaration

<flag name="three" value="3" />

ensuite, on pourrait ont écrit myflags="three" au lieu de myflags="one|two", pour des résultats identiques en tant que 3 == 1|2.

Personnellement, j'aime pour toujours inclure

<flag name="none" value="0" /> <!-- or "normal, "regular", and so on -->
<flag name="all" value="15" /> <!-- 15 == 1|2|4|8 -->

ce qui va me permettre d'annuler ou de l'ensemble de tous les indicateurs à la fois.

Plus subtilement, il peut être le cas qu'un drapeau est implicite par un autre. Ainsi, dans notre exemple, supposons que l' eight drapeau a été établi, devrait forcer l' four drapeau (si ce n'était pas déjà le cas). Nous avons ensuite pu re-définir eight de pré-inclure, comme c'était le cas, l' four drapeau,

<flag name="eight" value="12" /> <!-- 12 == 8|4 -->

Enfin, si vous devez déclarer les attributs dans un projet de bibliothèque mais que vous souhaitez appliquer dans les mises en page d'un autre projet (en fonction de la lib), vous aurez besoin d'utiliser un préfixe d'espace de noms que vous devez lier dans le XML de l'élément racine. E. g.,

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X