Cómo compilar una app simple con elementos de texto componibles

1. Antes de comenzar

En este codelab, usarás Jetpack Compose para compilar una app para Android simple que muestre un mensaje de cumpleaños en la pantalla.

Requisitos previos

  • Saber crear una app en Android Studio
  • Saber ejecutar una app en un emulador o dispositivo Android

Qué aprenderás

  • Cómo escribir funciones de componibilidad, como Text, Column y Row
  • Cómo mostrar texto en tu app en un diseño
  • Cómo darle formato al texto, por ejemplo, cambiar su tamaño

Qué compilarás

  • Una app para Android que muestra un saludo de cumpleaños en formato de texto, que, una vez creada, se verá como esta captura de pantalla:

fdf3fc55ab1d348a.png

Requisitos

  • Una computadora con Android Studio instalado

2. Cómo configurar una app de Feliz cumpleaños

En esta tarea, configurarás un proyecto en Android Studio con la plantilla de actividad vacía y cambiarás el mensaje de texto por un saludo de cumpleaños personalizado.

Cómo crear un proyecto de actividad vacía

  1. En el diálogo Welcome to Android Studio, selecciona la opción New Project.
  2. En el diálogo New Project, selecciona Empty Activity y haz clic en Next.
  3. En el campo Name, ingresa Happy Birthday, selecciona un nivel de API mínimo de 24 (Nougat) en el campo Minimum SDK y haz clic en Finish.

ff60c8aef54e55e5.png

  1. Espera a que Android Studio cree los archivos del proyecto y compílalo.
  2. Haz clic en fd26b2e3c2870c3.png Run 'app'.

La app debería verse tal como se muestra en la siguiente captura de pantalla:

51ca4dec519ee45c.png

Cuando creaste esta app de Feliz cumpleaños con la plantilla de actividad vacía, Android Studio configuró recursos para una app básica para Android, que incluía un mensaje de Hello Android! (¡Hola, Android!) en la pantalla. En este codelab, aprenderás cómo llega ese mensaje, cómo cambiar el texto por un saludo de cumpleaños y cómo agregar mensajes adicionales y aplicarles formato.

¿Qué es una interfaz de usuario (IU)?

La interfaz de usuario (IU) de una app es lo que ves en la pantalla: texto, imágenes, botones y muchos otros tipos de elementos, así como la forma en que esta información se presenta en pantalla. Así es como la app muestra elementos al usuario y cómo este interactúa con ella.

Esta imagen contiene un botón en el que se puede hacer clic, un mensaje de texto y un campo de entrada de texto donde los usuarios pueden ingresar datos.

cb6997dfd11668c4.png

Botón en el que se puede hacer clic

50a9b402fd9037c0.png

Mensaje de texto dentro de una tarjeta

17794ea52cfb5473.png

Campo de entrada de texto

Cada uno de estos elementos se denomina componente de la IU. Casi todo lo que ves en la pantalla de tu app es un elemento de la IU (también conocido como componente de la IU). Pueden ser interactivos, como un botón en el que se puede hacer clic o un campo de entrada editable, o pueden ser imágenes decorativas.

En las siguientes apps, intenta encontrar tantos componentes de IU como puedas.

mostrando apps recomendadas

En este codelab, trabajarás con un elemento de la IU que muestra texto llamado elemento Text.

3. ¿Qué es Jetpack Compose?

Jetpack Compose es un kit de herramientas moderno para crear IUs de Android. Compose simplifica y acelera el desarrollo de IUs en Android con menos código, herramientas potentes y capacidades intuitivas de Kotlin. Con Compose, puedes compilar tu IU a partir de la definición de un conjunto de funciones, llamadas funciones de componibilidad, que toman datos y describen elementos de la IU.

Funciones de componibilidad

Las funciones de componibilidad son los componentes básicos de una IU en Compose. Una función de componibilidad cumple con lo siguiente:

  • Describe alguna parte de tu IU.
  • No devuelve nada.
  • Toma información y genera lo que se muestra en la pantalla.

Anotaciones

Las anotaciones son una forma de adjuntar información adicional al código. Esta información ayuda a herramientas como el compilador de Jetpack Compose y a otros desarrolladores a comprender el código de la app.

Para aplicar una anotación, se agrega un prefijo al nombre (la anotación) con el carácter @ al comienzo de la declaración en la que se hará la anotación. Se pueden anotar diferentes elementos de código, incluidas propiedades, funciones y clases. Más adelante en el curso, aprenderás sobre las clases.

El siguiente diagrama es un ejemplo de una función con anotaciones:

Diagrama que muestra la anatomía de una función de componibilidad en la que la anotación con el carácter de prefijo @ es componible seguido de la declaración de la función.

El siguiente fragmento de código tiene ejemplos de propiedades con anotaciones. Las usarás en los próximos codelabs.

// Example code, do not copy it over

@Json
val imgSrcUrl: String

@Volatile
private var INSTANCE: AppDatabase? = null

Anotaciones con parámetros

Las anotaciones pueden tomar parámetros. Proporcionan información adicional a las herramientas que las procesan. Los siguientes son algunos ejemplos de la anotación @Preview con y sin parámetros.

Captura de pantalla de Android Studio en la que se muestra el código y la vista previa

Anotación sin parámetros

Captura de pantalla de Android Studio en la que se muestra el código y la vista previa

Anotación que muestra la vista previa del segundo plano

Captura de pantalla de Android Studio en la que se muestra el código y la vista previa

Anotación con un título de vista previa

Puedes pasar varios parámetros a la anotación, como se muestra aquí.

fd2ad3c2e7c8a9c7.png

Anotación con un título de vista previa y la IU del sistema (la pantalla del teléfono)

Jetpack Compose incluye una amplia gama de anotaciones integradas. En el curso, hasta el momento, ya viste las anotaciones @Composable y @Preview. Más adelante, aprenderás más anotaciones y sus usos.

Ejemplo de una función de componibilidad

La función de componibilidad tiene la anotación @Composable. Todas estas funciones deben tener esta anotación. La anotación informa al compilador de Compose que esta función está diseñada para convertir datos en IU. Te recordamos que un compilador es un programa especial que toma el código que escribiste, lo analiza línea por línea y lo traduce a algo que la computadora puede comprender (lenguaje automático).

Este fragmento de código es un ejemplo de una función simple de componibilidad a la que le pasan datos (el parámetro de la función name) y los usa para renderizar un elemento de texto en la pantalla.

@Composable
fun Greeting(name: String) {
    Text(text = "Hello $name!")
}

Algunas notas sobre las funciones de componibilidad:

  • Jetpack Compose se basa en funciones de componibilidad. Estas funciones te permiten definir la IU de tu app de manera programática describiendo cómo debería verse, en lugar de enfocarse en el proceso de construcción de la IU. Para crear una función de componibilidad, agrega la anotación @Composable al nombre de la función.
  • Estas funciones pueden aceptar parámetros, que permiten que la lógica de la app describa o modifique la IU. En este caso, tu elemento de la IU acepta una String para que pueda saludar al usuario por su nombre.

Observa las funciones de componibilidad en el código

  1. En Android Studio, abre el archivo MainActivity.kt.
  2. Desplázate hasta la función GreetingPreview(). Esta función de componibilidad ayuda a obtener una vista previa de la función Greeting(). Como práctica recomendada, las funciones siempre deben tener un nombre que describa su funcionalidad. Cambia el nombre de esta función a BirthdayCardPreview().
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        Greeting("Android")
    }
}

Las funciones de componibilidad pueden llamar a otras funciones del mismo tipo. En este fragmento de código, la función de vista previa llama a la función de componibilidad Greeting().

Observa que la función anterior también tiene otra anotación, una anotación @Preview con un parámetro antes de la anotación @Composable. Obtén más información sobre los argumentos que se pasaron a la anotación @Preview más adelante en el curso.

Nombres de funciones de componibilidad

La función de Compose que no devuelve nada y lleva la anotación @Composable DEBE tener un nombre con letra mayúscula inicial (pascal case). Esta es una convención de nomenclatura según la cual la primera letra de cada palabra de una palabra compuesta lleva mayúsculas. La diferencia entre este formato y el de mayúsculas mediales (camel case) es que, en el primer caso, todas las palabras se escriben con mayúscula inicial. En el segundo caso, la primera palabra puede estar en cualquiera de las dos opciones.

La función de Compose tiene las siguientes características:

  • DEBE ser un sustantivo: DoneButton().
  • NO debe ser un verbo ni una frase verbal: DrawTextField().
  • NO debe ser una preposición convertida en sustantivo: TextFieldWithLink().
  • NO debe ser un adjetivo: Bright().
  • NO debe ser un adverbio: Outside().
  • Los sustantivos PUEDEN estar precedidos por adjetivos descriptivos: RoundIcon().

Para obtener más información, consulta Cómo asignar nombres a funciones de componibilidad.

Ejemplo de código; no lo copies

// Do: This function is a descriptive PascalCased noun as a visual UI element
@Composable
fun FancyButton(text: String) {}

// Do: This function is a descriptive PascalCased noun as a non-visual element
// with presence in the composition
@Composable
fun BackButtonHandler() {}

// Don't: This function is a noun but is not PascalCased!
@Composable
fun fancyButton(text: String) {}

// Don't: This function is PascalCased but is not a noun!
@Composable
fun RenderFancyButton(text: String) {}

// Don't: This function is neither PascalCased nor a noun!
@Composable
fun drawProfileImage(image: ImageAsset) {}

4. Panel Design de Android Studio

Android Studio te permite obtener una vista previa de las funciones de componibilidad dentro del IDE, en lugar de instalar la app en un emulador o dispositivo Android. Como aprendiste en la ruta de aprendizaje anterior, puedes obtener una vista previa de la apariencia de tu app en el panel Design de Android Studio.

c284448a820d577c.png

La función de componibilidad debe proporcionar valores predeterminados para cualquier parámetro para obtener una vista previa. Por este motivo, se recomienda no obtener una vista previa de la función Greeting() directamente. En su lugar, debes agregar otra función (BirthdayCardPreview() en este caso) que llame a la función Greeting() con un parámetro adecuado.

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        Greeting("Android")
    }
}

Para ver tu vista previa, sigue estos pasos:

  1. En la función BirthdayCardPreview(), cambia el argumento "Android" en la función Greeting() por tu nombre.
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        Greeting("James")
    }
}
  1. Compila tu código. La vista previa debería actualizarse automáticamente.

Deberías ver la vista previa actualizada.

a9d045e42c47ca1b.png

5. Cómo agregar un nuevo elemento de texto

En esta tarea, quitarás el saludo de Hello $name! y agregarás un saludo de cumpleaños.

Cómo agregar una nueva función de componibilidad

  1. En el archivo MainActivity.kt, borra la definición de la función Greeting(). Más adelante, agregarás tu propia función para mostrar el saludo en el codelab.

Quita el siguiente código

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}
  1. Dentro de la función onCreate(), observa que la llamada a función Greeting() ahora es de color rojo. Este color rojo indica un error. Coloca el cursor sobre esta llamada a función y Android Studio mostrará información sobre el error.

f5635be4356320a7.png

  1. Borra la llamada a función Greeting() junto con sus argumentos de las funciones onCreate() y BirthdayCardPreview(). Tu archivo MainActivity.kt será similar al siguiente:
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HappyBirthdayTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                }
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
    }
}
  1. Antes de la función BirthdayCardPreview(), agrega una nueva función llamada GreetingText(). No olvides agregar la anotación @Composable antes de la función, ya que será una función de Compose que describirá un elemento componible Text.
@Composable
fun GreetingText() {
}
  1. La práctica recomendada es que el elemento componible acepte un parámetro Modifier y pase ese modifier a su primer elemento secundario. Aprenderás más sobre Modifier y los elementos secundarios en las tareas y los codelabs posteriores. Por ahora, agrega un parámetro Modifier a la función GreetingText().
@Composable
fun GreetingText(modifier: Modifier = Modifier) {
}
  1. Agrega un parámetro message de tipo String a la función de componibilidad GreetingText().
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
}
  1. En la función GreetingText(), agrega un elemento Text componible que pase el mensaje de texto como un argumento con nombre.
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
    Text(
        text = message
    )
}

Esta función GreetingText() muestra texto en la IU. Para ello, llama a la función de componibilidad Text().

Cómo obtener una vista previa de la función

En esta tarea, obtendrás una vista previa de la función GreetingText() en el panel Design.

  1. Llama a la función GreetingText() dentro de la función BirthdayCardPreview().
  2. Pasa un argumento de tipo String a la función GreetingText(), un saludo de cumpleaños a tu amigo. Si lo deseas, puedes personalizarlo con su nombre, como "Happy Birthday Sam!".
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        GreetingText(message = "Happy Birthday Sam!")
    }
}
  1. El panel Design, se actualiza automáticamente. Obtén una vista previa de tus cambios.

fd1260ace2f0f7b0.png

6. Cómo cambiar el tamaño de la fuente

Agregaste texto a tu interfaz de usuario, pero aún no parece la app final. En esta tarea, aprenderás a cambiar el tamaño, el color del texto y otros atributos que afectan el aspecto del elemento de texto. También puedes experimentar con diferentes tamaños y colores de fuente.

Píxeles escalables

Los píxeles escalables (SP) son una unidad de medida para el tamaño de fuente. Los elementos de la IU en apps para Android usan dos unidades de medición diferentes: los píxeles independientes de la densidad (DP), que usarás más tarde para el diseño, y los píxeles escalables (SP). De forma predeterminada, la unidad de SP tiene el mismo tamaño que la unidad de DP, pero cambia según el tamaño de texto que prefiera el usuario en la configuración del teléfono.

  1. En el archivo MainActivity.kt, desplázate hasta el elemento componible Text() de la función GreetingText().
  2. Pasa un argumento fontSize a la función Text() como un segundo argumento con nombre y establécelo en un valor de 100. sp.
Text(
    text = message,
    fontSize = 100.sp
)

Android Studio destaca el código .sp, ya que debes importar algunas clases o propiedades para compilar tu app.

8032c2d4926903d5.png

  1. Haz clic en .sp, que destaca Android Studio.
  2. Haz clic en Import en la ventana emergente para importar androidx.compose.ui.unit.sp y así usar la propiedad de extensión .sp.
  1. Desplázate hasta la parte superior del archivo y observa las sentencias import, donde deberías ver una sentencia import androidx.compose.ui.unit.sp, lo que significa que Android Studio agrega el paquete a tu archivo.

e073e9d3465e080c.png

  1. Observa la vista previa actualizada del tamaño de fuente. El motivo de la superposición del mensaje es que debes especificar la altura de la línea.

b001a2c51b985d0.png

  1. Actualiza el elemento Text componible de modo que incluya la altura de la línea.
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
    Text(
        text = message,
        fontSize = 100.sp,
        lineHeight = 116.sp,
    )
}

cefc09e773d1f29a.png

Ahora puedes experimentar con diferentes tamaños de fuente.

7. Cómo agregar otro elemento de texto

En las tareas anteriores, agregaste un mensaje de cumpleaños para tu amigo. En esta tarea, firmarás la tarjeta con tu nombre.

  1. En el archivo MainActivity.kt, desplázate hasta la función GreetingText().
  2. Pasa a la función un parámetro from de tipo String para tu firma.
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier)
  1. Después del mensaje de cumpleaños componible de tipo Text, agrega otro elemento Text componible que acepte un argumento de text establecido en el valor from.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Text(
        // ...
    )
    Text(
        text = from
    )
}
  1. Agrega un argumento con nombre fontSize establecido en un valor de 36.sp.
Text(
    text = from,
    fontSize = 36.sp
)
  1. Desplázate hasta la función BirthdayCardPreview().
  2. Agrega otro argumento String para firmar la tarjeta, como "From Emma".
GreetingText(message = "Happy Birthday Sam!", from ="From Emma")
  1. Observa la vista previa.

ac82fe1c68eb4599.png

Una función de componibilidad podría describir varios elementos de la IU. Sin embargo, si no proporcionas un lineamiento para organizarlos, Compose podría ordenarlos de una forma que no te guste. Por ejemplo, el código anterior genera dos elementos de texto que se superponen entre sí porque no hay un lineamiento para organizar los dos elementos componibles.

En tu próxima tarea, aprenderás a organizar estos elementos en una fila y en una columna.

8. Cómo organizar los elementos de texto en una fila y columna

Jerarquía de la IU

La jerarquía de la IU se basa en la contención, es decir, un componente puede contener uno o más componentes. A veces, se usan los términos superior y secundario. El contexto aquí es que los elementos superiores de la IU contienen elementos secundarios de la IU, los cuales, a su vez, pueden contener elementos secundarios de la IU. En esta sección, aprenderás sobre los elementos componibles Column, Row y Box, que pueden actuar como elementos superiores de la IU.

9270b7e10f954dcb.png

Los tres elementos de diseño estándar básicos en Compose son los elementos Column, Row y Box componibles. En el siguiente codelab, obtendrás más información sobre el elemento componible Box.

Una columna con tres elementos organizados de forma vertical y una fila que muestra tres elementos organizados de forma horizontal

Column, Row y Box son funciones de componibilidad, y toman contenido de este tipo como argumentos, por lo que puedes colocar elementos dentro de estos componentes de diseño. Por ejemplo, cada elemento secundario dentro de un elemento Row que admite composición se coloca de forma horizontal uno al lado del otro en una fila.

// Don't copy.
Row {
    Text("First Column")
    Text("Second Column")
}

Estos elementos de texto se muestran uno al lado del otro en la pantalla, como se ve en esta imagen.

Los bordes azules son solo para fines de demostración y no se mostrarán.

6f74a11c03564a61.png

Sintaxis de expresión lambda final

En el fragmento de código anterior, observa que se usan llaves en lugar de paréntesis en la función de componibilidad Row. Esto se llama sintaxis de expresión lambda final. Más adelante en el curso, aprenderás sobre las lambdas y la sintaxis de expresión lambda final en detalle. Por ahora, familiarízate con esta sintaxis de Compose de uso general.

Kotlin ofrece una sintaxis especial para pasar funciones como parámetros a funciones cuando el último parámetro es una función.

el parámetro de función es el último

Cuando pasas una función como ese parámetro, puedes usar la sintaxis de expresión lambda final. En lugar de colocar el cuerpo de la función junto con el nombre de la función entre paréntesis ({}), debes colocar los paréntesis junto con el cuerpo de la función después de su nombre. Esta práctica es recomendada y común en Compose, por lo que debes familiarizarte con la apariencia del código.

Por ejemplo, el último parámetro en la función de componibilidad Row() es el parámetro content, una función que describe los elementos secundarios de la IU. Supongamos que deseas crear una fila que contenga tres elementos de texto. Este código funcionaría, pero es muy engorroso usar el parámetro con nombre para la expresión lambda final:

Row(
    content = {
        Text("Some text")
        Text("Some more text")
        Text("Last text")
    }
)

Como el parámetro content es el último de la firma de la función y pasas su valor como una expresión lambda (por ahora, no hay problema si no sabes qué es una lambda; solo familiarízate con la sintaxis), puedes quitar el parámetro content y los paréntesis de la siguiente manera:

Row {
    Text("Some text")
    Text("Some more text")
    Text("Last text")
}

Cómo organizar los elementos de texto en una fila

En esta tarea, organizarás los elementos de texto de tu app en una fila para evitar la superposición.

  1. En el archivo MainActivity.kt, desplázate hasta la función GreetingText().
  2. Agrega el elemento Row componible alrededor de los elementos de texto de modo que muestre una fila con dos de esos elementos. Selecciona los dos elementos componibles Text y haz clic en la bombilla. Selecciona Surround with widget > Surround with Row.

bb8e10def9aa7b7e.png

ca2ff1086fb0802c.png

Ahora la función debería verse como este fragmento de código:

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Row {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
        )
        Text(
            text = from,
            fontSize = 36.sp
        )
    }
}
  1. Android Studio importa automáticamente la función Row. Desplázate hasta la parte superior y observa la sección de importación. Se debería haber agregado import androidx.compose.foundation.layout.Row.
  2. Observa la vista previa actualizada en el panel Design. Cambia temporalmente el tamaño de la fuente del mensaje de cumpleaños a 30.sp.

El saludo de cumpleaños y la firma se muestran uno al lado de la otra en una fila.

La vista previa se ve mucho mejor ahora que no hay superposición. Sin embargo, esto no es lo que quieres, ya que no hay suficiente espacio para tu firma. En la próxima tarea, organizarás los elementos de texto en una columna para resolver este problema.

Cómo organizar los elementos de texto en una columna

En esta tarea, es tu turno para cambiar la función GreetingText() para organizar los elementos de texto en una columna. La vista previa debería verse tal como se muestra en la siguiente captura de pantalla:

785f6c6e087b03b.png

Ahora que intentaste hacerlo por tu cuenta, no dudes en comparar tu código con el de la solución en este fragmento:

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp
        )
        Text(
            text = from,
            fontSize = 36.sp
        )
    }
}

Observa el paquete importado automáticamente por Android Studio:

import androidx.compose.foundation.layout.Column

Recuerda que debes pasar el parámetro modificador al elemento secundario en los elementos componibles. Eso significa que debes pasar el parámetro modificador al elemento Column componible.

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(modifier = modifier) {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp
        )
        Text(
            text = from,
            fontSize = 36.sp
        )
    }
}

9. Cómo agregar un saludo a la app

Una vez que estés conforme con la vista previa, es momento de agregar el elemento componible a tu app en el dispositivo o el emulador.

  1. En el archivo MainActivity.kt, desplázate hasta la función onCreate().
  2. Llama a la función GreetingText() desde el bloque Surface.
  3. Pasa la función GreetingText(), tu saludo de cumpleaños y la firma.

La función onCreate() completa debería verse como este fragmento de código:

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HappyBirthdayTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
                }
            }
        }
    }
}
  1. Compila y ejecuta tu app en el emulador.

433859d648d9b26.png

Cómo centrar el saludo

  1. Para alinear el saludo en el centro de la pantalla, agrega un parámetro llamado verticalArrangement y configúralo en Arrangement.Center. Obtendrás más información sobre verticalArrangement en un codelab posterior.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        // ...
    }
}
  1. Agrega un padding de 8.dp en la columna. Una práctica recomendada es usar valores de padding en incrementos de 4.dp.
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier.padding(8.dp)
    ) {
        // ...
    }
}
  1. Para embellecer aún más tu app, centra el texto del saludo usando textAlign.
Text(
    text = message,
    fontSize = 100.sp,
    lineHeight = 116.sp,
    textAlign = TextAlign.Center
)

ac614110dd73da93.png

En la captura de pantalla anterior, solo el saludo está centrado debido al parámetro textAlign. La firma, From Emma, tiene la alineación predeterminada a la izquierda.

  1. Agrega padding a la firma y alinea la derecha.
Text(
    text = from,
    fontSize = 36.sp,
    modifier = Modifier
        .padding(16.dp)
        .align(alignment = Alignment.End)
)

4c8c1e27bc2f6869.png

Adopta las prácticas recomendadas

Se recomienda pasar los atributos del modificador junto con el modificador desde el elemento componible superior. Actualiza el parámetro del modificador en el GreetingText() de la siguiente manera:

onCreate()

Surface(
    //...
) {
    GreetingText(
        message = "Happy Birthday Sam!",
        from = "From Emma",
        modifier = Modifier.padding(8.dp)
    )
}

GreetingText()

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        // ...
    }
}

Compila y ejecuta tu app en el emulador para ver el resultado final.

74dd02e4f7fa1780.png

10. Cómo obtener el código de la solución

El MainActivity.kt completo es el siguiente:

package com.example.happybirthday

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.happybirthday.ui.theme.HappyBirthdayTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            HappyBirthdayTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    GreetingText(
                        message = "Happy Birthday Sam!",
                        from = "From Emma",
                        modifier = Modifier.padding(8.dp)
                    )
                }
            }
        }
    }
}

@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
    Column(
        verticalArrangement = Arrangement.Center,
        modifier = modifier
    ) {
        Text(
            text = message,
            fontSize = 100.sp,
            lineHeight = 116.sp,
            textAlign = TextAlign.Center
        )
        Text(
            text = from,
            fontSize = 36.sp,
            modifier = Modifier
                .padding(16.dp)
                .align(alignment = Alignment.End)
        )
    }
}

@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
    HappyBirthdayTheme {
        GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
    }
}

11. Conclusión

Creaste tu app de Feliz cumpleaños.

En el siguiente codelab, agregarás una foto a tu app y cambiarás la alineación de los elementos de texto para embellecerla.

Resumen

  • Jetpack Compose es un kit de herramientas moderno para crear IU de Android. Jetpack Compose simplifica y acelera el desarrollo de IU en Android con menos código, herramientas potentes y APIs intuitivas de Kotlin.
  • La interfaz de usuario (IU) de una app es lo que ves en la pantalla: texto, imágenes, botones y muchos otros tipos de elementos.
  • Las funciones de componibilidad son los componentes fundamentales de Compose. Una función de este tipo es aquella que describe alguna parte de tu IU.
  • La función de componibilidad tiene la anotación @Composable. Esta anotación informa al compilador de Compose que esta función está diseñada para convertir datos en IU.
  • Los tres elementos de diseño estándar básicos de Compose son Column, Row, y Box. Son funciones Composable y que toman contenido de este tipo, por lo que puedes colocar elementos dentro de ellas. Por ejemplo, cada elemento secundario dentro de un Row se ubicará de forma horizontal uno al lado del otro.

Más información