Déclaration des attributs stylables dans Android

il y a très peu de documentation sur l'étiquette declare-styleable par laquelle nous pouvons déclarer des styles personnalisés pour les composants. J'ai trouvé cette liste de valeurs valides pour l'attribut format de la balise attr . Bien que ce soit agréable, cela 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'attribut format peut évidemment être défini à une combinaison de valeurs. Vraisemblablement, l'attribut format aide l'analyseur à interpréter une valeur de style réelle. Puis j'ai découvert ceci 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>

tous deux semblent déclarer un ensemble de valeurs autorisées pour le style indiqué.

donc j'ai deux questions:

  1. Quelle est la différence entre un style attribut qui peut prendre un ensemble de enum les valeurs et l'un qui peut prendre une série de flag valeurs?
  2. est-ce que quelqu'un connaît une meilleure documentation sur le fonctionnement de declare-styleable (autre que la rétro-ingénierie du code source Android)?
74
demandé sur Laurence Gonsalves 2011-05-16 20:28:04

2 réponses

il y a cette question ici: définir coutume attire avec certains info, mais pas beaucoup.

et ce post . Il a de bonnes informations sur les drapeaux et les énums:

attribut personnalisé XML Flags

Les drapeaux

sont des types d'attributs spéciaux dans qu'ils sont autorisés seulement un très petit sous-ensemble de valeurs, à savoir ceux qui sont définis sous la attribut de la balise. Les options sont spécifiées par un attribut "name" et une "valeur" attribut. Les noms sont requis pour être unique dans ce type d'attribut mais les valeurs ne doivent pas être. C'est la raison qu'au cours de l'évolution de la plateforme Android que nous avions "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 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é.

l'attribut valeur 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 compilateur Android est heureux de accepter soit.

attribut personnalisé XML Enums

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

pour mettre cela en contexte, supposons que je crée une coutume 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 attribut de format" entier " et suivre celui avec l'enum:

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

la seule stipulation lors de l'utilisation D'Énums de cette manière, c'est qu'un développeur en utilisant votre vue personnalisée pourrait placer intentionnellement la valeur "-1" dans les paramètres de mise en page. Ce serait déclencher la logique du cas particulier de "scroll_to_top."De tels imprévus (ou attendu) comportement pourrait rapidement reléguer votre bibliothèque à l'héritage code " pile si les valeurs Enum étaient choisis mal.


Comme Je L'Ai voyez-le, les valeurs réelles que vous pouvez ajouter en réalité à un attribut est limité par ce que vous pouvez en obtenir. Consultez la référence de classe AttributeSet 1519420920" ici pour plus de conseils.

vous pouvez obtenir:

  • booléens ( getAttributeBooleanValue ),
  • flotteurs ( getAttributeFloatValue ),
  • ints ( getAttributeIntValue ),
  • ints (comme getAttributeUnsignedIntValue ),
  • et des chaînes de caractères ( getAttributeValue )
68
répondu Aleadam 2017-05-23 12:02:42

la réponse de @Aleadam est très utile, mais imho omet une différence majeure entre 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 valeurs de ce dernier peuvent être combinées, cependant, en utilisant le bitwise ou l'opérateur.

un exemple, dans 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>

Dans res/layout/mylayout.xml nous pouvons maintenant faire 1519220920"

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

ainsi un enum sélectionne une de ses valeurs possibles, tandis que les drapeaux peuvent être combinés. Les valeurs numériques devraient refléter cette différence, typiquement vous voudrez la séquence de passer 0,1,2,3,... pour les enums (à utiliser comme indices de tableau, disons) et les drapeaux de passer 1,2,4,8,... afin qu'ils puissent être ajoutés ou supprimés indépendamment, en utilisant bitwise ou | pour combiner les drapeaux.

nous pourrions explicitement définir "meta flags" avec des valeurs qui ne sont pas une puissance de 2, et donc introduire une sorte de raccourci pour les combinaisons courantes. Par exemple, si nous l'avions inclus dans notre myflags déclaration

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

alors nous aurions pu écrire myflags="three" au lieu de myflags="one|two" , pour des résultats complètement identiques comme 3 == 1|2 .

personnellement, J'aime toujours inclure

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

qui me permettra de désactiver ou de mettre tous les drapeaux en même temps.

Plus subtilement, il pourrait être le cas, un drapeau est implicite par un autre. Ainsi, dans notre exemple, supposons que le drapeau eight étant activé, force le drapeau four à être activé (s'il ne l'était pas déjà). Nous pourrions alors redéfinir eight pour pré-inclure, pour ainsi dire, le drapeau four , 1519220920"

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

enfin, si vous déclarez les attributs dans un projet de bibliothèque mais que vous voulez les appliquer dans les layouts d'un autre projet (dépendant de la lib), vous aurez besoin d'utiliser un namespace préfixe que vous devez lier dans L'élément racine XML. Par exemple,

<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>
61
répondu Rad Haring 2014-03-12 19:53:18