Temas, colores, tipografías y formas en Jetpack Compose
Antonio Leiva

Si vienes del sistema clásico de vistas, recordarás que toda la definición de temas se hacía de una forma bastante tediosa a través de styles en XML.

Si odias tu vida (o estás en una App donde mezclas XMLs y Jetpack Compose), aún puedes seguir usando esos temas gracias a la librería de Accompanist.

Pero lo ideal en Jetpack Compose es usar sus temas, que también se definen en Kotlin, y hoy te voy a explicar las bases de cómo funcionan.

¡Atención! Si quieres acceder más rápido a todo el contenido en vídeo, organizado, con contenido extra, soporte y muchas más sorpresas, puedes apuntarte gratis a mi formación Compose Expert y ver gratis el primer módulo de más de 3 horas con todo lo necesario para empezar.

Material Design, el tema por defecto

Aunque Jetpack Compose no nos obliga a ello, si queremos empezar rápido con un diseño ya probado y adaptado a dispositivos Android, podemos optar por Material Design.

Material Design es el sistema de diseño creado por Google para adaptarse a todas las situaciones y todos los tamaños de pantalla.

En Jetpack Compose, gracias a unas pocas modificaciones en el tema, todos los componentes se adaptarán al estilo definido siguiendo las reglas de estilo de Material Design.

¿Cómo está estructurado el tema?

Nada más crear un proyecto, verás una estructura como la siguiente dentro del paquete ui:

Esto ya te va a dar una idea bastante clara de lo que se puede configurar en los temas de Compose:

  • Theme: aquí es donde vive el tema. Un tema se compone del resto de componentes
  • Color: los colores que el tema va a usar
  • Type: las tipografías para los distintos pesos de las fuentes. Verás que tienen nombres que recuerdan mucho a HTML
  • Shape: las formas para usar en los distintos componentes de UI. Hay 3 tamaños: pequeño, mediano y grande, y define qué forma tomarán los componentes según su tamaño.

Definiendo el Tema (Theme)

Para usar el tema Material, lo único que necesitamos es rodear nuestro código con el Composable MaterialTheme:

Materialtheme {
    MainScreen()
}

De esta forma estaría usando el tema por defecto, pero “casualmente”, tenemos los siguientes argumentos con los que podemos configurar todo lo anterior:

MaterialTheme(
    colors = colors,
    typography = Typography,
    shapes = Shapes
) {
    MainScreen
}

Quizá recuerdes que cuando creamos el proyecto, realmente ya teníamos un tema propio creado. En mi caso lo llamó MyMoviesTheme, y está definido en el archivo Theme.kt.

Es tan sencillo como un composable que define cómo se configura ese MaterialTheme, para que no lo tengas que repetir cada vez que necesites usarlo.

Pero tiene alguna peculiaridad que vamos a ver:

@Composable
fun MyMoviesTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}

Por un lado, como argumento podemos definir si queremos que se use el tema claro u oscuro, y por defecto coge la configuración en la que esté el sistema.

Pero imagina qué fácil sería poner en tu App una setting que le permita al usuario elegir si quiere un tema distinto al del sistema, y pasárselo por aquí como argumento.

En función del tema, elige una paleta de colores, y luego llama a MaterialTheme como ya hemos visto.

¡No hay ninguna magia aquí, solo Composables!

En este archivo de Themes también tenemos definidas las paletas de colors light y dark:

private val DarkColorPalette = darkColors(
    primary = Purple200,
    primaryVariant = Purple700,
    secondary = Teal200
)

private val LightColorPalette = lightColors(
    primary = Purple500,
    primaryVariant = Purple700,
    secondary = Teal200

Está cogiendo los colores por defecto y sustituyendo solo algunos. En este caso primary, primaryVariant y secondary.

¿Pero qué son esos nombres y dónde se definen los colores? Pues lo vemos ya mismo

Los colores

El tema Material define una serie de colores que luego se usan por defecto en los distintos componentes según como definen las guías de estilo. Tenemos estos colores, y en esta tabla se muestran los valores por defecto:

Diagram of Material color scheme displaying the baseline Material color theme
Imagen extraída de material.io

Si quieres saber más sobre teoría de colores en Material Design, puedes verla aquí.

El fichero de Color.kt es muy sencillo, solo tiene una definición de colores con sus nombres:

val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)

Si quieres crear tu propia paleta de colores, puedes usar el generador de paletas de colores de Google.

Tipografía

El tema te deja definir distintos niveles de tipografía en función del peso que quieras que tenga dentro de la UI, o la funcionalidad a la que se asocia.

Hay un gran número de estilos definidos por defecto, algunos de los cuales Compose usará en los lugares donde las guías de estilo así lo definen.

Aquí las tienes todas definidas, y con sus valores por defecto:

Imagen obtenida de material.io

Tenemos los siguientes grupos de fuentes:

  • Headings (H1…H6): Para los textos más destacados y que más queremos que se vean
  • Subtitles: Subtítulos para usar bajo los títulos, como información secundaria
  • Body: contenido principal, usado sobre todo cuando tenemos textos largos
  • Button: la tipografía usada en los botones
  • Caption y Overline: las más pequeñas, para poner pies de fotos o información sobre algún título.

En el archivo Type.kt tienes una personalización muy básica de las tipografías, para que luego puedas modificarlo a tu gusto:

val Typography = Typography(
    body1 = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp
    )
)

El constructor de Typography permite sobrescribir cualquiera de los estilos por defecto.

Si te fijas, se usa el mismo TextStyle que expliqué en el artículo de Textos en Jetpack Compose.

En las Cards estábamos usando h6, vamos a modificarlo en el tema:

h6 = TextStyle(
    fontFamily = FontFamily.Default,
    fontWeight = FontWeight.ExtraBold,
    fontStyle = FontStyle.Italic,
    fontSize = 25.sp
)

Formas (shapes)

Esto es algo relativamente nuevo dentro de los temas de Material, que nos permite definir la forma que van a tener los componentes en Material, como por ejemplo las Cards o los botones.

Por defecto usa una forma con los bordes ligeramente redondeados, como vemos en la imagen anterior.

Se pueden definir tres formas, para objetos pequeños, medianos y grandes. Como seguramente no sabrás cuál entra en cada grupo, en las guías tienes un listado de componentes y en qué categoría caen.

Las formas por defecto las puedes encontrar en Shape.kt:

val Shapes = Shapes(
    small = RoundedCornerShape(4.dp),
    medium = RoundedCornerShape(4.dp),
    large = RoundedCornerShape(0.dp)
)

Pero imagina que quieres que los componentes de tamaño medio tengan los bordes cortados en vez de redondeados. Puedes hacer:

medium = CutCornerShape(16.dp)

Un pequeño paseo por los temas en Jetpack Compose

Y aquí acaba el repaso sobre las configuraciones que nos permite el tema.

Como ves, es mucho más sencillo que con XML, y hay algunas cosas que no se pueden hacer, como crear estilos reutilizables.

Pero no es mayor problema, porque gracias a Kotlin, podemos extraer el componente configurado como queramos como un nuevo Composable reutilizable, y así usarlo en todos los sitios donde lo necesitemos.

Si te quedan dudas sobre cómo funcionan los temas o cómo solucionar algún caso particular, no dudes en utilizar los comentarios.

También te animo a que te apuntes al contenido gratuito de Compose Expert, para poder aprender las bases de Jetpack Compose de forma rápida y efectiva. También podrás unirte a la comunidad y preguntar las dudas que te surjan, entre otras muchas sorpresas.

Apúntate ahora a Compose Expert y accede a más de 3h de contenido gratuito, soporte, extras y mucho más totalmente gratis.

Por el momento, la formación gratuita acaba aquí. Espero que lo hayas disfrutado, y cualquier sugerencia para nuevos vídeos será más que bienvenida.

Un abrazo

Quizá también te interese…

Usando Cards de Material Design en Jetpack Compose

Usando Cards de Material Design en Jetpack Compose

Tenemos ya una App de lo más resultona después de todos los artículos que hemos visto hasta ahora. Puedes encontrarlos todos bien ordenaditos de forma gratuita en el área privada de Compose Expert. https://youtu.be/iZiXpWRIl3U Pero antes de finalizar nuestro camino,...

Navegación en Jetpack Compose con Navigation Compose

Navegación en Jetpack Compose con Navigation Compose

Jetpack Compose es un cambio de paradigma enorme en muchos aspectos. Cambia la forma de pensar en casi todos los puntos involucrados en el desarrollo de una App Android. Y la navegación no iba a ser menos. ¿Cómo se navega en Jetpack Compose? ¿Qué opciones tenemos?...

5 consejos para estructurar el código en Jetpack Compose

5 consejos para estructurar el código en Jetpack Compose

Escribir la interfaz con código es genial, pero puede ser que pronto se nos vaya de las manos. Aunque la forma de escribir el código de Jetpack Compose es muy natural y relativamente directa, sí que es verdad que en pro de la flexibilidad, también hay algunos...

0 comentarios

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de Antonio Leiva Gordillo, con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad *