Recursos en Compose

Jetpack Compose puede acceder a los recursos definidos en tu proyecto de Android. En este documento, se explican algunas de las API que ofrece Compose para ello.

Los recursos son los archivos adicionales y el contenido estático que usa tu código, como mapas de bits, definiciones de diseño, strings de interfaz de usuario, instrucciones de animación, etc. Si no estás familiarizado con los recursos de Android, consulta la guía de descripción general de recursos de apps.

Strings

El tipo de recurso más común son tus strings. Usa la API de stringResource para recuperar una string definida de manera estática en tus recursos XML.

// In the res/values/strings.xml file
// <string name="compose">Jetpack Compose</string>

// In your Compose code
Text(
    text = stringResource(R.string.compose)
)

stringResource también funciona con formato posicional.

// In the res/values/strings.xml file
// <string name="congratulate">Happy %1$s %2$d</string>

// In your Compose code
Text(
    text = stringResource(R.string.congratulate, "New Year", 2021)
)

Plurales de strings

Compose aún no ofrece un método directo para recuperar los plurales de String. Sin embargo, puedes usar el enfoque tradicional con el método getQuantityString de la clase Resources. Para acceder a Resources desde Context, usa la composición LocalContext local. Obtén más información sobre la composición local en la documentación de Interoperabilidad.

// In the res/strings.xml file
// <plurals name="runtime_format">
//    <item quantity="one">%1$d minute</item>
//    <item quantity="other">%1$d minutes</item>
// </plurals>

// In your Compose code
val resources = LocalContext.current.resources

Text(
    text = resources.getQuantityString(
        R.plurals.runtime_format, quantity, quantity
    )
)

Dimensiones

Del mismo modo, usa la API de dimensionResource para obtener las dimensiones de un archivo XML de recursos.

// In the res/values/dimens.xml file
// <dimen name="padding_small">8dp</dimen>

// In your Compose code
val smallPadding = dimensionResource(R.dimen.padding_small)
Text(
    text = "...",
    modifier = Modifier.padding(smallPadding)
)

Colores

Si adoptas Compose de forma incremental en tu app, usa la API de colorResource para obtener colores de un archivo XML de recursos.

// In the res/colors.xml file
// <color name="colorGrey">#757575</color>

// In your Compose code
Divider(color = colorResource(R.color.colorGrey))

colorResource funciona según lo esperado con colores estáticos, pero aplana los recursos de la lista de estados de color.

Recursos de imágenes y elementos vectoriales

Usa la API de painterResource para cargar interfaces dibujables en vectores o formatos de activos de trama, como PNG. No necesitas conocer el tipo de elemento de diseño. Simplemente usa painterResource en elementos componibles Image o modificadores paint.

// Files in res/drawable folders. For example:
// - res/drawable-nodpi/ic_logo.xml
// - res/drawable-xxhdpi/ic_logo.png

// In your Compose code
Icon(
    painter = painterResource(id = R.drawable.ic_logo),
    contentDescription = null // decorative element
)

painterResource decodifica y analiza el contenido del recurso en el subproceso principal.

Interfaces dibujables en vectores animadas

Usa la API de animatedVectorResource para cargar un archivo XML de elementos de interfaces dibujables en vector animadas. El método muestra una instancia de AnimatedImageVector. Para mostrar la imagen animada, usa el método painterFor a fin de crear un Painter que se pueda usar en los elementos componibles Image y Icon. El parámetro booleano atEnd del método painterFor indica si la imagen se debe dibujar al final de todas las animaciones. Si se usa con un estado mutable, los cambios en este valor activan la animación correspondiente.

// Files in res/drawable folders. For example:
// - res/drawable/animated_vector.xml

// In your Compose code
val image = animatedVectorResource(id = R.drawable.animated_vector)
val atEnd by remember { mutableStateOf(false) }
Icon(
    painter = image.painterFor(atEnd = atEnd),
    contentDescription = null // decorative element
)

Íconos

Jetpack Compose incluye el objeto Icons, que es el punto de entrada para usar íconos de material en Compose. Hay cinco temas de íconos distintos: Con relleno, Con contorno, Redondo, Dos tonos y Nítido. Cada tema contiene los mismos íconos, pero con un estilo visual distinto. Por lo general, debes elegir un tema y usarlo en tu aplicación para mayor coherencia.

Para dibujar un ícono, puedes usar el elemento componible Icon que aplica tonos y proporciona el tamaño del diseño que coincide con el ícono.

import androidx.compose.material.Icon

Icon(Icons.Rounded.Menu, contentDescription = "Localized description")

Algunos de los íconos que se usan con mayor frecuencia están disponibles como parte de la dependencia androidx.compose.material. Para usar otros íconos de Material, agrega la dependencia material-icons-extended al archivo build.gradle.

dependencies {
  ...
  implementation "androidx.compose.material:material-icons-extended:$compose_version"
}

Fuentes

Para usar fuentes en Compose, descarga y empaqueta los archivos de fuente directamente en tus APK colocándolos en la carpeta res/font.

Carga cada fuente con la API de Font y crea una FontFamily con ellas que puedas usar en TextStyle para crear tu propiaTypography. El siguiente código se tomó de la muestra de composición Crane y su archivo Typography.kt.

// Define and load the fonts of the app
private val light = Font(R.font.raleway_light, FontWeight.W300)
private val regular = Font(R.font.raleway_regular, FontWeight.W400)
private val medium = Font(R.font.raleway_medium, FontWeight.W500)
private val semibold = Font(R.font.raleway_semibold, FontWeight.W600)

// Create a font family to use in TextStyles
private val craneFontFamily = FontFamily(light, regular, medium, semibold)

// Use the font family to define a custom typography
val craneTypography = Typography(
    defaultFontFamily = craneFontFamily,
    /* ... */
)

// Pass the typography to a MaterialTheme that will create a theme using
// that typography in the part of the UI hierarchy where this theme is used
@Composable
fun CraneTheme(content: @Composable () -> Unit) {
    MaterialTheme(typography = craneTypography) {
        content()
    }
}

Obtén más información sobre la tipografía en la documentación de Temas en Compose.