Los estilos y temas de Android te permiten separar los detalles del diseño de tu app de la estructura y el comportamiento de la IU, de manera similar a las hojas de estilo en el diseño web.
Un estilo es una colección de atributos que especifica la apariencia de un solo View. Un estilo puede especificar atributos, como el color y el tamaño de fuente, el color de fondo y mucho más.
Un tema es una colección de atributos que se aplican a toda una app, actividad o jerarquía de vistas, no solo a una vista individual. Cuando aplicas un tema, cada vista de la app o actividad aplica cada uno de los atributos del tema que admite. Los temas también pueden aplicar estilos a elementos que no forman parte de la vista, como la barra de estado y el fondo de la ventana.
Los estilos y temas se declaran en un archivo de recursos de estilo en res/values/, que suele llamarse styles.xml.
Figura 1: Dos temas aplicados a la misma actividad: Theme.AppCompat (izquierda) y Theme.AppCompat.Light (derecha).
Temas versus estilos
Los temas y los estilos tienen muchas similitudes, pero se usan para diferentes propósitos. Los temas y los estilos tienen la misma estructura básica: un par clave-valor que asigna atributos a recursos.
Un estilo especifica atributos para un tipo de vista determinado. Por ejemplo, un estilo puede especificar los atributos de un botón. Cada atributo que especificas en un estilo es un atributo que puedes establecer en el archivo de diseño. Extraer todos los atributos a un estilo facilita su uso y mantenimiento en varios widgets.
Un tema define una colección de recursos con nombre a los que se puede hacer referencia mediante estilos, diseños, widgets, etcétera. Los temas asignan nombres semánticos, como colorPrimary, a los recursos de Android.
Los estilos y los temas se diseñaron para trabajar en conjunto. Por ejemplo, puedes tener un estilo que especifique
que una parte de un botón es colorPrimary y otra parte es
colorSecondary. Las definiciones reales de esos colores se proporcionan en el tema. Cuando
el dispositivo entra en modo nocturno, la app puede cambiar de su tema "claro" al "oscuro",
lo que modifica los valores de todos esos nombres de recursos. No es necesario que cambies los estilos, ya que estos usan los nombres semánticos y no las definiciones de color específicas.
Para obtener más información sobre cómo funcionan juntos los temas y los estilos, consulta la entrada de blog Estilo de Android: temas vs. estilos.
Cómo crear y aplicar un estilo
Para crear un estilo nuevo, abre el archivo res/values/styles.xml de tu proyecto. Para cada estilo que quieras crear, sigue estos pasos:
- Agrega un elemento
<style>con un nombre que identifique el estilo de forma exclusiva. - Agrega un elemento
<item>para cada atributo de estilo que quieras definir. El elementonamede cada elemento especifica un atributo que, de lo contrario, usarías como atributo XML en tu diseño. El valor del elemento<item>es el valor de ese atributo.
Por ejemplo, supongamos que defines el siguiente estilo:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="GreenText" parent="TextAppearance.AppCompat"> <item name="android:textColor">#00FF00</item> </style> </resources>
Puedes aplicar el estilo a una vista de la siguiente manera:
<TextView style="@style/GreenText" ... />
Cada atributo especificado en el estilo se aplica a esa vista si esta lo acepta. La vista ignora los atributos que no acepta.
Sin embargo, en lugar de aplicar un estilo a vistas individuales, por lo general, aplicas estilos como un tema para toda la app, actividad o colección de vistas, como se describe en otra sección de esta guía.
Cómo extender y personalizar un estilo
Cuando crees tus propios estilos, extiende siempre un estilo existente del framework o de la biblioteca de compatibilidad para mantener la compatibilidad con los estilos de la IU de la plataforma. Para extender un estilo, especifica el estilo que deseas extender con el atributo parent. Luego, puedes anular los atributos de estilo heredados y agregar otros nuevos.
Por ejemplo, puedes heredar la apariencia de texto predeterminada de la plataforma de Android y modificarla de la siguiente manera:
<style name="GreenText" parent="@android:style/TextAppearance"> <item name="android:textColor">#00FF00</item> </style>
Sin embargo, siempre hereda los estilos principales de tu app de la biblioteca de compatibilidad de Android. Los estilos de la biblioteca de compatibilidad proporcionan compatibilidad, ya que optimizan cada estilo para los atributos de la IU disponibles en cada versión. Los estilos de la biblioteca de compatibilidad suelen tener un nombre similar al del estilo de la plataforma, pero con AppCompat incluido.
Para heredar estilos de una biblioteca o de tu propio proyecto, declara el nombre del estilo superior sin la parte @android:style/ que se muestra en el ejemplo anterior. Por ejemplo, en el siguiente ejemplo, se heredan los estilos de apariencia de texto de la biblioteca de compatibilidad:
<style name="GreenText" parent="TextAppearance.AppCompat"> <item name="android:textColor">#00FF00</item> </style>
También puedes heredar estilos (excepto los de la plataforma) extendiendo el nombre de un estilo con una notación de puntos, en lugar de usar el atributo parent. Es decir, agrega el nombre del estilo que deseas heredar como prefijo del nombre de tu estilo, separado por un punto. Por lo general,
solo lo haces cuando extiendes tus propios estilos, no los de otras bibliotecas. Por ejemplo,
el siguiente estilo hereda todos los estilos de GreenText del ejemplo anterior
y, luego, aumenta el tamaño del texto:
<style name="GreenText.Large"> <item name="android:textSize">22dp</item> </style>
Puedes seguir heredando estilos de esta manera todas las veces que quieras encadenando más nombres.
Para saber qué atributos puedes declarar con una etiqueta <item>, consulta la tabla "Atributos XML" en las distintas referencias de clase. Todas las vistas admiten atributos XML de la clase base View, y muchas vistas agregan sus propios atributos especiales. Por ejemplo, los atributos XML de TextView incluyen el atributo android:inputType que puedes aplicar a una vista de texto que recibe entradas, como un widget EditText.
Cómo aplicar un estilo como un tema
Puedes crear un tema de la misma manera en que creas estilos. La diferencia radica en cómo lo aplicas: en lugar de aplicar un estilo con el atributo style en una vista, aplicas un tema con el atributo android:theme en la etiqueta <application> o en una etiqueta <activity> del archivo AndroidManifest.xml.
Por ejemplo, a continuación, se muestra cómo aplicar el tema "oscuro" de Material Design de la biblioteca de compatibilidad de Android a toda la app:
<manifest ... > <application android:theme="@style/Theme.AppCompat" ... > </application> </manifest>
Aquí se muestra cómo aplicar el tema "claro" a una sola actividad:
<manifest ... > <application ... > <activity android:theme="@style/Theme.AppCompat.Light" ... > </activity> </application> </manifest>
Cada vista de la app o actividad aplica los estilos que admite de los definidos en el tema determinado. Si una vista solo admite algunos de los atributos declarados en el estilo, aplicará únicamente esos atributos y omitirá los que no admita.
A partir de Android 5.0 (nivel de API 21) y la biblioteca de compatibilidad de Android v22.1, también puedes especificar el atributo android:theme para una vista en tu archivo de diseño. Esto modifica el tema para esa vista y cualquier vista secundaria, lo que es útil para alterar las paletas de colores del tema en una parte específica de tu interfaz.
En los ejemplos anteriores, se muestra cómo aplicar un tema, como Theme.AppCompat, que proporciona la biblioteca de compatibilidad de Android. Sin embargo, por lo general, querrás personalizar el tema para que se adapte a la marca de tu app. La mejor manera de hacerlo es extender estos estilos desde la biblioteca de compatibilidad y anular algunos de los atributos, como se describe en la siguiente sección.
Jerarquía de estilos
Android ofrece varias formas de establecer atributos en tu app para Android. Por ejemplo, puedes establecer atributos directamente en un diseño, aplicar un estilo a una vista, aplicar un tema a un diseño y, incluso, establecer atributos de manera programática.
Cuando elijas cómo diseñar tu app, ten en cuenta la jerarquía de estilos de Android. En general, usa temas y estilos tanto como sea posible para mantener la coherencia. Si especificas los mismos atributos en varios lugares, la siguiente lista determina qué atributos se aplican en última instancia. La lista se ordena de mayor a menor prioridad.
- Aplicar diseño a nivel de carácter o párrafo con intervalos de texto a clases derivadas de
TextView - Aplicar atributos de manera programática
- Aplicar atributos individuales directamente a una vista
- Aplicar un estilo a una vista
- Estilo predeterminado.
- Aplicar un tema a una colección de vistas, una actividad o toda tu app
- Aplicar un estilo específico de la vista, como configurar un
TextAppearanceen unTextView
Figura 2: El estilo de un span anula el de una textAppearance
TextAppearance
Una limitación es que puedes aplicar un solo estilo a un View. Sin embargo, en un TextView, también puedes especificar un atributo TextAppearance que funcione de manera similar a un estilo, como se muestra en el siguiente ejemplo:
<TextView ... android:textAppearance="@android:style/TextAppearance.Material.Headline" android:text="This text is styled via textAppearance!" />
TextAppearance te permite definir un diseño específico para el texto, mientras que el estilo de un View queda disponible para otros usos. Sin embargo, ten en cuenta que, si defines algún atributo de texto directamente en View o en un estilo, esos valores anularán los valores de TextAppearance.
TextAppearance admite un subconjunto de atributos de diseño que ofrece TextView. Para obtener la lista completa de atributos, consulta
TextAppearance.
Algunos atributos TextView comunes que no se incluyen son lineHeight[Multiplier|Extra], lines, breakStrategy y hyphenationFrequency.
TextAppearance funciona a nivel de caracteres y no de párrafos, por lo que no se admiten los atributos que afectan todo el diseño.
Personaliza el tema predeterminado
Cuando creas un proyecto con Android Studio, se aplica un tema de Material Design a tu app de forma predeterminada, como se define en el archivo styles.xml de tu proyecto. Este estilo AppTheme extiende un tema de la biblioteca de compatibilidad y, además, incluye anulaciones para los atributos de color que usan los elementos clave de la IU, como la barra de la app y el botón de acción flotante, si se usan. Por lo tanto, puedes personalizar rápidamente el diseño de color de tu app actualizando los colores proporcionados.
Por ejemplo, tu archivo styles.xml se ve similar al siguiente:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
Los valores de estilo son, en realidad, referencias a otros recursos de color, definidos en el archivo res/values/colors.xml del proyecto. Ese es el archivo que editas para cambiar los colores.
Consulta la descripción general de los colores de Material Design para mejorar la experiencia del usuario con colores dinámicos y colores personalizados adicionales.
Cuando conozcas tus colores, actualiza los valores en res/values/colors.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Color for the app bar and other primary UI elements. --> <color name="colorPrimary">#3F51B5</color> <!-- A darker variant of the primary color, used for the status bar (on Android 5.0+) and contextual app bars. --> <color name="colorPrimaryDark">#303F9F</color> <!-- a secondary color for controls like checkboxes and text fields. --> <color name="colorAccent">#FF4081</color> </resources>
Luego, puedes anular cualquier otro estilo que desees. Por ejemplo, puedes cambiar el color de fondo de la actividad de la siguiente manera:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> ... <item name="android:windowBackground">@color/activityBackground</item> </style>
Para obtener una lista de los atributos que puedes usar en tu tema, consulta la tabla de atributos en R.styleable.Theme. Cuando agregues estilos para las vistas de tu diseño, también podrás encontrar atributos en la tabla "Atributos XML" de las referencias de la clase de vista. Por ejemplo, todas las vistas admiten atributos XML de la clase View base.
La mayoría de los atributos se aplican a tipos específicos de vistas, mientras que algunos se aplican a todas las vistas. Sin embargo, algunos atributos de tema que se indican en R.styleable.Theme se aplican a la ventana de la actividad, no a las vistas del diseño. Por ejemplo, windowBackground cambia el fondo de la ventana y windowEnterTransition define una animación de transición que se usará cuando se inicie la actividad. Para obtener más detalles, consulta Cómo iniciar una actividad con una animación.
La biblioteca de compatibilidad de Android también proporciona otros atributos que puedes usar para personalizar tu tema extendido desde Theme.AppCompat, como el atributo colorPrimary que se muestra en el ejemplo anterior. Se recomienda verlos en el
archivo attrs.xml de la biblioteca.
También hay diferentes temas disponibles en la biblioteca de compatibilidad que tal vez quieras extender en lugar de los que se muestran en el ejemplo anterior. El mejor lugar para ver los temas disponibles es el archivo themes.xml de la biblioteca.
Cómo agregar estilos específicos de una versión
Si una versión nueva de Android agrega atributos de tema que quieres usar, puedes agregarlos a tu tema y, al mismo tiempo, mantener la compatibilidad con las versiones anteriores. Solo necesitas otro archivo styles.xml guardado en un directorio values que incluya el calificador de versión del recurso:
res/values/styles.xml # themes for all versions res/values-v21/styles.xml # themes for API level 21+ only
Como los estilos del archivo values/styles.xml están disponibles para todas las versiones, tus temas en values-v21/styles.xml pueden heredarlos. Esto significa que puedes evitar duplicar estilos si comienzas con un tema "base" y, luego, lo extiendes en tus estilos específicos de la versión.
Por ejemplo, para declarar transiciones de ventanas para Android 5.0 (nivel de API 21) y versiones posteriores, debes usar atributos nuevos. Por lo tanto, tu tema base en res/values/styles.xml puede verse de la siguiente manera:
<resources> <!-- Base set of styles that apply to all versions. --> <style name="BaseAppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/primaryColor</item> <item name="colorPrimaryDark">@color/primaryTextColor</item> <item name="colorAccent">@color/secondaryColor</item> </style> <!-- Declare the theme name that's actually applied in the manifest file. --> <style name="AppTheme" parent="BaseAppTheme" /> </resources>
Luego, agrega los estilos específicos de la versión en res/values-v21/styles.xml, de la siguiente manera:
<resources> <!-- extend the base theme to add styles available only with API level 21+ --> <style name="AppTheme" parent="BaseAppTheme"> <item name="android:windowActivityTransitions">true</item> <item name="android:windowEnterTransition">@android:transition/slide_right</item> <item name="android:windowExitTransition">@android:transition/slide_left</item> </style> </resources>
Ahora puedes aplicar AppTheme en tu archivo de manifiesto, y el sistema seleccionará los estilos disponibles para cada versión del sistema.
Para obtener más información sobre el uso de recursos alternativos para diferentes dispositivos, consulta Cómo proporcionar recursos alternativos.
Cómo personalizar estilos de widget
Cada widget del framework y la biblioteca de compatibilidad tiene un estilo predeterminado. Por ejemplo, cuando
estilizas tu app con un tema de la biblioteca de compatibilidad, se aplica el estilo
Widget.AppCompat.Button a una instancia de
Button. Si quieres aplicar un estilo de widget diferente a un botón, puedes hacerlo con el atributo style en tu archivo de diseño. Por ejemplo, en el siguiente código, se aplica el estilo de botón sin borde de la biblioteca:
<Button style="@style/Widget.AppCompat.Button.Borderless" ... />
Si quieres aplicar este estilo a todos los botones, puedes declararlo en el atributo buttonStyle de tu tema de la siguiente manera:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="buttonStyle">@style/Widget.AppCompat.Button.Borderless</item> ... </style>
También puedes extender los estilos de los widgets, como extender cualquier otro estilo, y, luego, aplicar el estilo de widget personalizado en tu diseño o tema.
Recursos adicionales
Para obtener más información sobre los temas y estilos, consulta los siguientes recursos adicionales:
Entradas de blog
- Android styling: themes vs styles
- Diseños de Android: Atributos comunes del tema
- Diseños de Android: Atributos de tema preferidos