Declaración de atributos elegibles en Android

Hay muy poca documentación sobre la etiqueta declare-styleable por la que podemos declarar estilos personalizados para los componentes. Encontré esta lista de valores válidos para el atributo format de la etiqueta attr . Mientras que es agradable hasta donde va, no explica cómo utilizar algunos de esos valores. Buscando attr.xml (la fuente de Android para los atributos estándar), descubrí que puedes hacer cosas como:

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

El atributo format puede evidentemente estar configurado con una combinación de valores. Presumiblemente, el atributo format ayuda al analizador a interpretar un valor de estilo real. Entonces descubrí esto en 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> 

Ambos parecen declarar un conjunto de valores permitidos para el estilo indicado.

Así que tengo dos preguntas:

  1. ¿Cuál es la diferencia entre un atributo de estilo que puede tomar uno de un conjunto de valores de enum y uno que puede tener un conjunto de valores de flag ?
  2. ¿Alguien sabe de alguna mejor documentación sobre cómo funcionan las declare-styleable (aparte de la ingeniería inversa del código fuente de Android)?

Hay esta pregunta aquí: Definir attrs personalizado con algo de información, pero no mucho.

Y este post . Tiene buena información sobre banderas y enums:

Banderas de atributos XML personalizados

Las banderas son tipos de atributo especiales en que se les permite sólo un subconjunto muy pequeño de valores, es decir, aquellos que se definen debajo de la etiqueta de atributo. Los indicadores se especifican mediante un atributo "nombre" y un atributo "valor". Los nombres deben ser únicos dentro de ese tipo de atributo pero los valores no tienen que ser. Esta es la razón por la que durante la evolución de la plataforma de Android tuvimos "fill_parent" y "match_parent" ambas asignaciones para el mismo comportamiento. Sus valores eran idénticos.

El atributo de nombre se asigna al nombre utilizado en el lugar de valor dentro del XML de presentación y no requiere un prefijo de espacio de nombres. Por lo tanto, para el "tilingMode" arriba he elegido "center" como el valor del atributo. Yo podría haber elegido tan fácilmente "estirado" o "repetir", pero nada más. Ni siquiera la sustitución de los valores reales habría sido permitida.

El atributo value debe ser un entero. La elección de la representación numérica hexadecimal o estándar depende de usted. Hay algunos lugares dentro del código de Android donde ambos se utilizan y el compilador de Android está feliz de aceptar cualquiera.

Enums de atributo XML personalizado

Los enums se utilizan de una manera casi idéntica como banderas con una provisión, que pueden ser utilizados indistintamente con números enteros. Bajo el capó Enums y enteros se asignan al mismo tipo de datos, es decir, un entero. Al aparecer en la definición de atributo con números enteros, los Enums sirven para prevenir "números mágicos" que siempre son malos. Esta es la razón por la que puede tener un "android: layout_width" con una dimensión, un número entero o una cadena con nombre "fill_parent".

Para poner esto en contexto, supongamos que creo un atributo personalizado llamado "layout_scroll_height" que acepta un número entero o una cadena "scroll_to_top". Para ello añadiría un atributo de formato "entero" y lo seguiría con el enum:

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

La única estipulación al usar Enums de esta manera es que un desarrollador que utilice su vista personalizada podría colocar el valor "-1" en los parámetros de diseño. Esto desencadenaría la lógica de caso especial de "scroll_to_top". Tal comportamiento inesperado (o esperado) podría relegar rápidamente su biblioteca a la pila del "código heredado" si los valores de Enum se escogían mal.


A mi modo de ver, los valores reales que puedes añadir en realidad a un atributo están limitados por lo que puedes obtener de él. Compruebe la referencia de clase AttributeSet aquí para obtener más sugerencias.

Usted puede obtener:

  • getAttributeBooleanValue ( getAttributeBooleanValue ),
  • Floats ( getAttributeFloatValue ),
  • getAttributeIntValue ( getAttributeIntValue ),
  • getAttributeUnsignedIntValue (como getAttributeUnsignedIntValue ),
  • Y cadenas ( getAttributeValue )

@Aleadam la respuesta es muy útil, pero imho omite una diferencia importante entre enum y flag . El primero está destinado a que elijamos uno, y sólo un valor cuando asignamos el atributo correspondiente a alguna Vista. Sin embargo, los valores de este último se pueden combinar utilizando el operador OR bit a bit.

Un ejemplo, 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 podemos hacer ahora

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

Así, un enum selecciona uno de sus valores posibles, mientras que los flags pueden combinarse. Los valores numéricos deben reflejar esta diferencia, por lo general usted querrá que la secuencia de ir 0,1,2,3,... para enums (que se utilizarán como índices de matriz, por ejemplo) y las banderas para ir 1,2,4,8,... para que puedan ser añadidos o eliminados independientemente, utilizando OR a bit | Para combinar banderas.

Podríamos definir explícitamente "banderas meta" con valores que no son un poder de 2, y así introducir una especie de abreviatura para combinaciones comunes. Por ejemplo, si hubiéramos incluido esto en nuestra declaración de myflags

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

Entonces podríamos haber escrito myflags="three" en lugar de myflags="one|two" , para resultados completamente idénticos como 3 == 1|2 .

Personalmente, me gusta incluir siempre

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

Lo que me permitirá desarmar o establecer todas las banderas a la vez.

Más sutilmente, podría ser el caso de que una bandera esté implícita en otra. Por lo tanto, en nuestro ejemplo, supongamos que la bandera eight que se está estableciendo debe forzar la bandera four a establecer (si no fuera ya). Podríamos entonces re-definir eight para pre-incluir, por así decirlo, la bandera four ,

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

Por último, si está declarando los atributos en un proyecto de biblioteca pero desea aplicarlos en diseños de otro proyecto (dependiendo de la lib), deberá utilizar un prefijo de espacio de nombres al que debe enlazar en el elemento raíz XML. P.ej,

 <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> 
  • Android añadiendo pie de página a ListView addFooterView ()?
  • Doclava - ¿Cómo generar versionado xml?
  • El contenido de los elementos debe consistir en datos de caracteres bien formados o marcado. AndroidManifest.xml
  • ¿Cuál es la historia con el espacio de nombres XML de Android?
  • Cómo agregar etiquetas en XML en Android?
  • Recursos de importación android de proyecto de biblioteca
  • Android Google Map error android.view.InflateException: Archivo XML binario línea # 6: error iniciando el fragmento de clase
  • Android Studio no identifica el archivo xml como archivo de diseño
  • Dibujar la forma de Android xml diagonal con triángulos
  • set Selector for Button Programmatically issues
  • Combinar lienzo y diseño (Android)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.