1. Antes de comenzar
En este codelab, usarás Jetpack Compose a fin de compilar una app para Android simple que muestre un mensaje de cumpleaños en la pantalla.
Requisitos previos
- Cómo crear una app en Android Studio
- Cómo ejecutar una app en un emulador o dispositivo Android
Qué aprenderás
- Cómo escribir funciones que admiten composición, como
Text
,Column
yRow
- Cómo mostrar texto en tu app
- Cómo darle formato al texto, como cambiar el tamaño del texto y el tamaño de la fuente
Qué compilarás
- Una app para Android que muestra un saludo de cumpleaños en formato de texto, que cuando termines se verá como esta captura de pantalla:
Requisitos
- Una computadora que tenga Android Studio instalado
2. Mira el video con instrucciones para compilar (opcional)
Si quieres ver cómo uno de los instructores del curso completa el codelab, reproduce el siguiente video.
Se recomienda expandir el video a pantalla completa (con este ícono en la esquina inferior derecha del video) para que puedas ver Android Studio y el código con mayor claridad.
Este paso es opcional. También puedes omitir el video y comenzar con las instrucciones del codelab de inmediato.
3. Cómo configurar una app de Feliz cumpleaños
En esta tarea, configurarás un proyecto en Android Studio con una plantilla de actividad de Compose vacía y cambiarás el mensaje de texto a un saludo de cumpleaños personalizado.
Cómo crear un proyecto de actividad de Compose vacía
- En el diálogo Welcome to Android Studio, selecciona la opción New Project.
- En el diálogo New Project, selecciona Empty Compose Activity y haz clic en Next.
- Ingresa
Happy Birthday
en el campo Name, selecciona un nivel mínimo de API de 21 (Lollipop) en el campo Minimum SDK y haz clic en Finish.
- Espera a que Android Studio cree los archivos del proyecto y compílalo.
- Haz clic en
Run 'app'.
La app debería verse tal como se muestra en la siguiente captura de pantalla:
Cuando creaste esta app de Feliz cumpleaños con la plantilla de actividad de Compose vacía, Android Studio configuró recursos para una app básica para Android, que incluía un mensaje de Hello Android! en la pantalla. En este codelab, aprenderás cómo llega ese mensaje, cómo cambiar el texto a 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 clics, un mensaje de texto y un campo de entrada de texto donde los usuarios pueden ingresar datos.
Botón en el que se puede hacer clic
Mensaje de texto
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 clics o un campo de entrada editable, o pueden ser imágenes decorativas.
En este codelab, trabajarás con un elemento de la IU que muestra texto llamado "elemento Text
".
4. ¿Qué es Jetpack Compose?
Jetpack Compose es un kit de herramientas moderno para crear IU de Android. Compose simplifica y acelera el desarrollo de IU 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 que admiten composición, que toman datos y emiten elementos de la IU.
Funciones que admiten composición
Las funciones que admiten composición son los componentes fundamentales de una IU en Compose. Una función que admite composición cumple con lo siguiente:
- Describe alguna parte de tu IU.
- No muestra nada.
- Toma información y genera lo que se muestra en la pantalla.
- Puede emitir varios elementos de la IU.
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:
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. A continuación, se muestran algunos ejemplos de anotaciones @preview
con y sin parámetros.
Anotación sin parámetros
Anotación que muestra la vista previa del segundo plano
Anotación con un título de vista previa
Puedes pasar varios parámetros a la anotación, como se muestra aquí.
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. Hasta el momento, en el curso, ya viste las anotaciones @Composable
y @Preview
. Más adelante, aprenderás más sobre las anotaciones y sus usos.
Ejemplo de una función que admite composición
La función que admite composición 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 que admite composición a la que le pasan datos (el parámetro de la función name
) y los usa para procesar un elemento de texto en la pantalla.
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
Algunas notas sobre las funciones que admiten composició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. - La función no muestra nada. Las funciones que admiten composición y que emiten la IU no necesitan mostrar nada porque describen el estado de pantalla deseado en lugar de construir elementos de la IU. En otras palabras, las funciones que admiten composición solo describen la IU; no la construyen ni la crean, por lo que no hay nada que mostrar.
Observa las funciones que admiten composición en el código
- En Android Studio, abre el archivo
MainActivity.kt
. - Desplázate hasta la función
DefaultPreview()
y bórrala. Agrega una nueva función que admite composición,BirthdayCardPreview()
, para obtener una vista previa de la funciónGreeting()
, de la siguiente manera. Como práctica recomendada, las funciones siempre deben tener un nombre que describa su funcionalidad.
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
BirthdayCardTheme {
Greeting("Android")
}
}
Las funciones que admiten composición 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 que admite composición 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 que admiten composición
La función de Compose que no muestra nada y lleva la anotación @Composable
DEBE tener un nombre con letra mayúscula inicial. 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 y minúsculas es que, en el primer caso, todas las palabras se escriben con mayúscula inicial. En el segundo caso, la primera palabra no lleva mayúsculas.
La función 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()
.
Este lineamiento se aplica tanto si la función emite elementos de la IU como si no lo hace. Para obtener más información, consulta Cómo asignar nombres a funciones que admiten composición.
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) {
5. Panel Design en Android Studio
Android Studio te permite obtener una vista previa de las funciones que admiten composición 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.
La función que admite composición debe proporcionar valores predeterminados para cualquier parámetro a fin de obtener una vista previa. Por este motivo, no puedes 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() {
BirthdayCardTheme {
Greeting("Android")
}
}
Aprenderás sobre el parámetro showBackground
en la anotación Preview
en codelabs posteriores.
Para ver tu vista previa, sigue estos pasos:
- Compila tu código.
La vista previa debería actualizarse automáticamente.
Otra forma de actualizar la vista previa es hacer clic en Build & Refresh en el panel Design.
- En la función
BirthdayCardPreview()
, cambia el argumento "Android"
en la funciónGreeting()
por tu nombre.
fun BirthdayCardPreview() {
BirthdayCardTheme {
Greeting("James")
}
}
- Haz clic en
Build & Refresh en el panel Design.
Deberías ver la vista previa actualizada.
6. Cómo agregar un nuevo elemento de texto
En esta tarea, quitarás el saludo de Hello Android!
y agregarás un saludo de cumpleaños.
Cómo agregar una nueva función que admite composición
- En el archivo
MainActivity.kt
, borra la definición de la funciónGreeting()
. Más adelante, agregarás tu propia función para mostrar el saludo en el codelab.
@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}
- Ten en cuenta que Android Studio destaca la llamada a la función
Greeting()
y, luego, coloca el cursor sobre ella para identificar el error.
- Borra de las funciones
onCreate()
yBirthdayCardPreview()
la llamada a la funciónGreeting()
junto con sus argumentos. Tu archivoMainActivity.kt
será similar al siguiente:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
BirthdayCardTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview(){
BirthdayCardTheme {
}
}
- Antes de la función
BirthdayCardPreview()
, agrega una nueva función llamadaBirthdayGreetingWithText()
. No olvides agregar la anotación@Composable
antes de la función, ya que será una función de Compose que emitirá un elementoText
que admite composición.
@Composable
fun BirthdayGreetingWithText() {
}
- Agrega un parámetro
message
de tipoString
a la funciónBirthdayGreetingWithText()
que admite composición.
@Composable
fun BirthdayGreetingWithText(message: String) {
}
- En la función
BirthdayGreetingWithText()
, agrega un elementoText()
que admite composición que pase el mensaje de texto como un argumento con nombre.
@Composable
fun BirthdayGreetingWithText(message: String) {
Text(
text = message
)
}
Esta función BirthdayGreetingWithText()
muestra texto en la IU. Para ello, llama a la función Text()
que admite composición.
Cómo obtener una vista previa de la función
En esta tarea, obtendrás una vista previa de la función BirthdayGreetingWithText()
en el panel Design.
- Llama a la función
BirthdayGreetingWithText()
dentro de la funciónBirthdayCardPreview()
. - Pasa un argumento de tipo
String
a la funciónBirthdayGreetingWithText()
, un saludo de cumpleaños a tu amigo. Si lo deseas, puedes personalizarlo con su nombre, como"Happy Birthday Sam!"
.
@Preview(showBackground = false)
@Composable
fun BirthdayCardPreview() {
BirthdayCardTheme {
BirthdayGreetingWithText( "Happy Birthday Sam!")
}
}
- En el panel Design, haz clic en
Build & Refresh y espera a que se complete la compilación para obtener una vista previa de tu función.
7. 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.
- En el archivo
MainActivity.kt
, desplázate hasta el elementoText()
que admite composición en la funciónBirthdayGreetingWithText()
. - Pasa a la función
Text()
un argumentofontSize
como un segundo argumento con nombre y establécelo en un valor de36.
sp
.
Text(
text = message,
fontSize = 36.sp
)
Android Studio destaca el código .sp
, ya que debes importar algunas clases o propiedades para compilar tu app.
- Haz clic en
.sp
, que destaca Android Studio. - Haz clic en Importar en la ventana emergente a fin de importar
androidx.compose.ui.unit.sp
para usar la propiedad de extensión.sp
.
- Desplázate hasta la parte superior del archivo y observa las sentencias
import
, donde deberías ver una sentenciaimport androidx.compose.ui.unit.sp
, lo que significa que Android Studio agregó el paquete a tu archivo.
- Haz clic en Build & Refresh en el panel Design para obtener la vista previa actualizada. Observa el cambio de tamaño de fuente en la vista previa del saludo.
Ahora puedes experimentar con diferentes tamaños de fuente.
8. 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.
- En el archivo
MainActivity.kt
, desplázate hasta la funciónBirthdayGreetingWithText()
. - Pasa a la función un parámetro
from
de tipoString
para tu firma.
fun BirthdayGreetingWithText(message: String, from: String)
- Después del mensaje de cumpleaños de tipo
Text
que admite composición, agrega otro elementoText
de este tipo que acepte un argumento detext
establecido en el valorfrom
.
Text(
text = from
)
- Agrega un argumento con nombre
fontSize
establecido en un valor de24.sp
.
Text(
text = from,
fontSize = 24.sp
)
- Desplázate hasta la función
BirthdayCardPreview()
. - Agrega otro argumento
String
a fin de firmar la tarjeta, como"- from Emma"
.
BirthdayGreetingWithText( "Happy Birthday Sam!", "- from Emma")
- Haz clic en Build & Refresh en el panel Design.
- Observa la vista previa.
Una función que admite composición podría emitir 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 que admiten composición.
En tu próxima tarea, aprenderás a organizar estos elementos en una fila y en una columna.
9. 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 Columna, Fila y Cuadro, que admiten composición y pueden actuar como elementos superiores de la IU.
Los tres elementos de diseño estándar básicos en Compose son Column
, Row
y Box
, que admiten composición. En el siguiente codelab, obtendrás más información sobre el elemento Box
que admite composición.
Column
, Row
y Box
son funciones que admiten composición 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 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.
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 Row
que admite composición. 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 la 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.
Si quieres pasar una función como ese parámetro, puedes usar la sintaxis de expresión lambda final. En lugar de colocar la función junto con el nombre de la función entre paréntesis, debes colocar los paréntesis después del nombre de la función. Esta práctica es 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 Row()
que admite composición es el parámetro content
, una función que emite los elementos secundarios de la IU. Supongamos que deseas crear una fila que contenga tres elementos de texto. Este código funciona, pero es muy engorroso:
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.
- En el archivo
MainActivity.kt
, desplázate hasta la funciónBirthdayGreetingWithText()
. - Agrega el elemento
Row
que admite composición alrededor de los elementos de texto de modo que muestre una columna con dos de esos elementos.
Ahora la función debería verse como este fragmento de código:
@Composable
fun BirthdayGreetingWithText(message: String, from: String) {
Row{
Text(
text = message,
fontSize = 36.sp,
)
Text(
text = from,
fontSize = 24.sp,
)
}
}
- Haz clic en
Row
, en el fragmento de código, que está destacado. - Ten en cuenta que Android Studio te ofrece varias opciones de importación para
Row
. - Haz clic en Importar.
- Selecciona el paquete de la clase
androidx.compose.ui
que comienza conRow(androidx.compose.ui.Modifier, androidx.compose.foundation.layout.Argument.Horizontal, androidx
....
.
- Haz clic en Build & Refresh para actualizar la vista previa en el panel Design.
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 a fin de resolver este problema.
Cómo organizar los elementos de texto en una columna
En esta tarea, cambiarás la función BirthdayGreetingWithText()
para organizar los elementos de texto en una columna. No olvides hacer clic en Build & Refresh con el objetivo de actualizar la vista previa, que debería ser similar a esta captura de pantalla:
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 BirthdayGreetingWithText(message: String, from: String) {
Column {
Text(
text = message,
fontSize = 36.sp,
)
Text(
text = from,
fontSize = 24.sp,
)
}
}
Importa este paquete cuando Android Studio te lo solicite:
import androidx.compose.foundation.layout.Column
10. Cómo mostrar los elementos en el dispositivo
Una vez que estés satisfecho con la vista previa, deberás ejecutar la app en tu dispositivo o emulador.
- En el archivo
MainActivity.kt
, desplázate hasta la funciónonCreate()
. - Llama a la función
BirthdayGreetingWithText()
desde el bloqueSurface
. - Pasa la función
BirthdayGreetingWithText()
, 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 {
BirthdayCardTheme {
// A surface container that uses the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
BirthdayGreetingWithText( "Happy Birthday Sam!", "- from Emma")
}
}
}
}
}
- Compila y ejecuta tu app en el emulador.
11. Cómo obtener el código de la solución
El MainActivity.kt
completo es el siguiente:
package com.example.android.happybirthday
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
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 that uses the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
BirthdayGreetingWithText( "Happy Birthday Sam!", "- from Emma")
}
}
}
}
}
@Composable
fun BirthdayGreetingWithText(message: String, from: String) {
Column {
Text(
text = message,
fontSize = 36.sp,
)
Text(
text = from,
fontSize = 24.sp,
)
}
}
@Preview(showBackground = false)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
BirthdayGreetingWithText( "Happy Birthday Sam!", "- from Emma")
}
}
12. 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 API 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 que admiten composición son los componentes fundamentales de Compose. Una función de este tipo es aquella que describe alguna parte de tu IU.
- La función que admite composición 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
yBox
. Son funciones que admiten composición y que toman contenido de este tipo, por lo que puedes colocar elementos dentro de ellas. Por ejemplo, cada elemento secundario dentro de unRow
se ubicará de forma horizontal uno al lado del otro.