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 (función experimental)

Usa la API de pluralStringResource para cargar un plural con una cantidad determinada.

// 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
Text(
    text = pluralStringResource(
        R.plurals.runtime_format,
        quantity,
        quantity
    )
)

Cuando se usa el método pluralStringResource, debes pasar dos veces la cantidad si tu string incluye un formato de string con un número. Por ejemplo, para la string %1$d minutes, el primer parámetro de recuento selecciona el plural adecuado y el segundo se inserta en el marcador de posición %1$d. Si tus strings plurales no incluyen formato de string, no es necesario que pases el tercer parámetro a pluralStringResource.

Para obtener más información sobre los plurales, consulta la documentación sobre las strings de cantidad.

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="purple_200">#FFBB86FC</color>

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

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 AnimatedImageVector.animatedVectorResource para cargar un archivo XML de elementos de diseño vectorial animados. El método muestra una instancia de AnimatedImageVector. Para mostrar la imagen animada, usa el método rememberAnimatedVectorPainter 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 rememberAnimatedVectorPainter 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/ic_hourglass_animated.xml

// In your Compose code
val image =
    AnimatedImageVector.animatedVectorResource(R.drawable.ic_hourglass_animated)
val atEnd by remember { mutableStateOf(false) }
Icon(
    painter = rememberAnimatedVectorPainter(image, 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.

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 {
  def composeBom = platform('androidx.compose:compose-bom:2024.03.00')
  implementation composeBom

  implementation 'androidx.compose.material:material-icons-extended'
}

Fuentes

Para usar fuentes en Compose, descarga y empaqueta los archivos de fuente directamente en tus APKs 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 de 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(
    titleLarge = TextStyle(
        fontFamily = 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()
    }
}

Para usar fuentes descargables en Compose, consulta la página Fuentes descargables.

Más información sobre la tipografía en la documentación de Temas en Compose