Existe muy poca documentación sobre la declare-styleable
etiqueta mediante la cual podemos declarar estilos personalizados para componentes. Encontré esta lista de valores válidos para el format
atributo de la attr
etiqueta. Si bien eso es bueno en la medida de lo posible, no explica cómo usar algunos de esos valores. Navegando 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 format
atributo evidentemente se puede ajustar a una combinación de valores. Presumiblemente, el format
atributo ayuda al analizador a interpretar un valor de estilo real. Luego 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.
Entonces tengo dos preguntas:
- ¿Cuál es la diferencia entre un atributo de estilo que puede tomar uno de un conjunto de
enum
valores y uno que puede tomar un conjunto deflag
valores? - ¿Alguien sabe de alguna documentación mejor sobre cómo
declare-styleable
funciona (aparte de la ingeniería inversa del código fuente de Android)?
fuente
enum
yflag
.La respuesta de @Aleadam es muy útil, pero en mi humilde opinión, omite una diferencia importante entre
enum
yflag
. El primero está destinado a que elijamos uno, y solo un valor cuando asignamos el atributo correspondiente para 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
ahora podemos hacer<com.example.MyWidget myenum="two" myflags="one|two" ... />
Entonces, una enumeración selecciona uno de sus valores posibles, mientras que las banderas se pueden combinar. Los valores numéricos deben reflejar esta diferencia, por lo general, querrá que la secuencia vaya
0,1,2,3,...
para enumeraciones (para usarse como índices de matriz, por ejemplo) y banderas para1,2,4,8,...
que se puedan agregar o eliminar de forma independiente, usando OR bit|
a bit para combinar banderas.Podríamos definir explícitamente "metabanderas" con valores que no sean una potencia de 2, y así introducir una especie de abreviatura de combinaciones comunes. Por ejemplo, si hubiéramos incluido esto en nuestra
myflags
declaración<flag name="three" value="3" />
entonces podríamos haber escrito
myflags="three"
en lugar demyflags="one|two"
, para obtener resultados completamente idénticos a3 == 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 poner todas las banderas a la vez.
Más sutilmente, podría darse el caso de que una bandera esté implícita en otra. Entonces, en nuestro ejemplo, suponga que la
eight
bandera que se está configurando debería forzar la configuración de lafour
bandera (si no lo estaba ya). A continuación, podríamos volver a definireight
para incluir previamente, por así decirlo, lafour
bandera,<flag name="eight" value="12" /> <!-- 12 == 8|4 -->
Por último, si declara los atributos en un proyecto de biblioteca pero desea aplicarlos en diseños de otro proyecto (que depende de la biblioteca), deberá usar un prefijo de espacio de nombres que debe vincular 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>
fuente