Cómo agregar una lista desplazable

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

1. Antes de comenzar

En este codelab, aprenderás a crear una lista desplazable en tu app con Jetpack Compose.

Trabajarás con la app Affirmations, que muestra una lista de afirmaciones vinculadas con hermosas imágenes para aportar optimismo a tu día.

Los datos ya están allí; lo único que debes hacer es tomarlos y mostrarlos en la IU.

Requisitos previos

  • Conocimientos de listas de Kotlin
  • Experiencia en el diseño de diseños con Jetpack Compose
  • Experiencia en la ejecución de apps en un dispositivo o emulador

Qué aprenderás

  • Cómo crear una tarjeta de material design con Jetpack Compose
  • Cómo crear una lista desplazable con Jetpack Compose

Qué compilarás

  • Tomarás una aplicación existente y agregarás una lista desplazable a la IU.

El producto terminado se verá de la siguiente manera:

f6f09800b74f4700.png

Requisitos

  • Una computadora con acceso a Internet, un navegador web y Android Studio
  • Acceso a GitHub

Descarga el código de inicio

En Android Studio, abre la carpeta basic-android-kotlin-compose-training-affirmations.

  1. Navega a la página de repositorio de GitHub del proyecto.
  2. Verifica que el nombre de la rama coincida con el especificado en el codelab. Por ejemplo, en la siguiente captura de pantalla, el nombre de la rama es main.

1e4c0d2c081a8fd2.png

  1. En la página de GitHub de este proyecto, haz clic en el botón Code, el cual abre una ventana emergente.

1debcf330fd04c7b.png

  1. En la ventana emergente, haz clic en el botón Download ZIP para guardar el proyecto en tu computadora. Espera a que se complete la descarga.
  2. Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
  3. Haz doble clic en el archivo ZIP para descomprimirlo. Se creará una carpeta nueva con los archivos del proyecto.

Abre el proyecto en Android Studio

  1. Inicia Android Studio.
  2. En la ventana Welcome to Android Studio, haz clic en Open.

d8e9dbdeafe9038a.png

Nota: Si Android Studio ya está abierto, selecciona la opción de menú File > Open.

8d1fda7396afe8e5.png

  1. En el navegador de archivos, ve hasta donde se encuentra la carpeta de proyecto descomprimido (probablemente en Descargas).
  2. Haz doble clic en la carpeta del proyecto.
  3. Espera a que Android Studio abra el proyecto.
  4. Haz clic en el botón Run 8de56cba7583251f.png para compilar y ejecutar la app. Asegúrate de que funcione como se espera.

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 el ícono Este símbolo muestra 4 esquinas en un cuadrado destacado para indicar el modo de pantalla completa. 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. Crea una clase de datos de elemento de lista

Cómo crear una clase de datos para una Affirmation

En las apps para Android, las listas se componen de elementos de ese tipo. En el caso de datos individuales, esto podría ser algo simple, como una string o un valor entero. Para los elementos de lista que tienen varios datos, como una imagen y texto, necesitarás una clase que contenga todas estas propiedades. Las clases de datos son un tipo de clase que solo contiene propiedades y pueden proporcionar algunos métodos de utilidad para trabajar con esas propiedades.

  1. Crea un paquete nuevo en com.example.affirmations. 4a51cb670bbec405.png

Asígnale el nombre model al nuevo paquete. El paquete model contendrá el modelo de datos al que representará una clase de datos. Esa clase de datos estará compuesta de propiedades que representan la información relevante a lo que será una Affirmation (afirmación), que constará de un recurso de string y un recurso de imagen. Los paquetes son directorios que contienen clases e incluso otros directorios.

9ea1f8880ca90ea0.png

  1. Crea una clase nueva en el paquete com.example.affirmations.model. a9515a8b47715a22.png

Asígnale el nombre Affirmation a la nueva clase y conviértela en una clase de datos.

b36be7f428fd1672.png

  1. Cada Affirmation consiste en una imagen y una string. Crea dos propiedades val en la clase de datos Affirmation. Una debe llamarse stringResourceId y la otra imageResourceId. Ambos deben ser valores enteros.

Affirmation.kt

data class Affirmation(
   val stringResourceId: Int,
   val imageResourceId: Int
)
  1. Etiqueta la propiedad stringResourceId con la anotación @StringRes y la etiqueta imageResourceId con @DrawableRes. stringResourceId representa un ID para el texto de afirmación almacenado en un recurso de strings. imageResourceId representa un ID para la imagen de afirmación almacenada en un recurso de elementos de diseño.

Affirmation.kt

data class Affirmation(
   @StringRes val stringResourceId: Int,
   @DrawableRes val imageResourceId: Int
)
  1. Ahora, abre el archivo Datasource.kt en el paquete com.example.affirmations.data y quita los comentarios de la clase Datasource.

Datasource.kt

class Datasource() {
   fun loadAffirmations(): List<Affirmation> {
       return listOf<Affirmation>(
           Affirmation(R.string.affirmation1, R.drawable.image1),
           Affirmation(R.string.affirmation2, R.drawable.image2),
           Affirmation(R.string.affirmation3, R.drawable.image3),
           Affirmation(R.string.affirmation4, R.drawable.image4),
           Affirmation(R.string.affirmation5, R.drawable.image5),
           Affirmation(R.string.affirmation6, R.drawable.image6),
           Affirmation(R.string.affirmation7, R.drawable.image7),
           Affirmation(R.string.affirmation8, R.drawable.image8),
           Affirmation(R.string.affirmation9, R.drawable.image9),
           Affirmation(R.string.affirmation10, R.drawable.image10))
   }
}

4. Agrega una lista a tu app

Cómo crear una tarjeta de elemento de lista

Esta app está diseñada para mostrar una lista de afirmaciones. El primer paso para configurar la IU a fin de mostrar una lista es crear un elemento de lista. Cada elemento de afirmación consta de una imagen y una string. Los datos para cada uno de estos elementos vienen con el código de inicio, y crearás el componente de IU para mostrar ese elemento.

El elemento consta de un elemento de componibilidad Card, que a su vez contiene un elemento Image y uno de componibilidad Text. En Compose, un elemento Card es una superficie que muestra contenido y acciones en un solo contenedor. La tarjeta de Affirmation se verá de la siguiente manera:

95111184aed54fa3.png

La tarjeta muestra una imagen con un poco de texto debajo. Este diseño vertical se puede lograr usando un elemento de componibilidad Column unido en un elemento de componibilidad Card. Puedes probarlo por tu cuenta o seguir los pasos a continuación para lograrlo.

  1. Abre el archivo MainActivity.kt.

1e348baaf91552f4.png

  1. Crea un método nuevo debajo del método AffirmationApp(), llamado AffirmationCard(), y anótalo con la anotación @Composable.

MainActivity.kt

@Composable
fun AffirmationApp() {
   val context = LocalContext.current
   AffirmationsTheme {

   }
}

@Composable
fun AffirmationCard() {

}
  1. Edita la firma del método para tomar un objeto Affirmation como parámetro. El objeto Affirmation proviene del paquete model.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation) {

}
  1. Agrega un parámetro modifier a la firma. Establece un valor predeterminado de Modifier para el parámetro.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {

}
  1. Dentro del método AffirmationCard, llama al elemento de componibilidad Card. Pasa los siguientes parámetros: modifier y elevation. Pasa un objeto Modifier con el atributo padding establecido en 8.dp para el parámetro modifier. Pasa un valor de 4.dp para elevation. La propiedad elevation se aborda en detalle más adelante.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
  }
}
  1. Agrega un elemento de componibilidad Column dentro del elemento Card. Los elementos dentro de un elemento de componibilidad Column se organizan automáticamente en la IU. Esto te permite colocar una imagen sobre el texto asociado. Por el contrario, un elemento de componibilidad Row organiza los elementos contenidos de manera horizontal.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = modifier.padding(8.dp), elevation = 4.dp) {
    Column {
    }
  }
}
  1. Agrega un elemento de componibilidad Image dentro del cuerpo de la lambda del elemento Column. Recuerda que un elemento de componibilidad Image siempre requiere un recurso para mostrarse y una contentDescription. El recurso debe ser un painterResource que se pase al parámetro painter. El método painterResource cargará elementos de diseño vectoriales o formatos de elementos de trama, como PNG. Además, debes pasar un elemento stringResource para el parámetro contentDescription.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
    Column {
      Image(
        painter = painterResource(affirmation.imageResourceId),
        contentDescription = stringResource(affirmation.stringResourceId)
      )
    }
  }
}
  1. Además de los parámetros painter y contentDescription, debes pasar un modifier y un contentScale. Un contentScale determina cómo se debe escalar y mostrar la imagen. El objeto Modifier debe tener establecido el atributo fillMaxWidth y una altura de 194.dp. El contentScale debe ser ContentScale.Crop.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
    Column {
      Image(
        painter = painterResource(affirmation.imageResourceId),
        contentDescription = stringResource(affirmation.stringResourceId),
        modifier = Modifier
          .fillMaxWidth()
          .height(194.dp),
        contentScale = ContentScale.Crop
      )
    }
  }
}
  1. Dentro del Column, crea un elemento de componibilidad Text después del elemento Image. Pasa un stringResource de la affirmation.stringResourceId al parámetro text, luego un objeto Modifier con el atributo padding establecido en 16.dp, y establece un tema de texto pasando MaterialTheme.typography.h6 al parámetro style.

MainActivity.kt

@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
  Card(modifier = Modifier.padding(8.dp), elevation = 4.dp) {
    Column {
      Image(
        painter = painterResource(affirmation.imageResourceId),
        contentDescription = stringResource(affirmation.stringResourceId),
        modifier = Modifier
          .fillMaxWidth()
          .height(194.dp),
        contentScale = ContentScale.Crop
      )
      Text(
        text = stringResource(affirmation.stringResourceId),
        modifier = Modifier.padding(16.dp),
        style = MaterialTheme.typography.h6
      )
    }
  }
}

Cómo obtener una vista previa del elemento de componibilidad AffirmationCard

La tarjeta es el núcleo de la IU para la app de Affirmations, y lograste crearla. Para comprobar que la tarjeta se vea bien, puedes crear un elemento de componibilidad a fin de obtener una vista previa sin tener que iniciar toda la app.

  1. Crea un método privado llamado AffirmationCardPreview(). Anota el método con @Preview y @Composable.

MainActivity.kt

@Preview
@Composable
private fun AffirmationCardPreview() {
}
  1. Dentro del método, llama al elemento de componibilidad AffirmationCard y pásale un nuevo objeto Affirmation con el recurso de strings R.string.affirmation1 y el recurso de elementos de diseño R.drawable.image1 que se pasaron a su constructor.

MainActivity.kt

@Preview
@Composable
private fun AffirmationCardPreview() {
  AffirmationCard(Affirmation(R.string.affirmation1, R.drawable.image1))
}
  1. Abre la pestaña Split y obtendrás una vista previa de AffirmationCard. Si es necesario, haz clic en Build & Refresh, en el panel Design, para mostrar la vista previa. 84904da4a33413ce.png

Crea la lista

El componente del elemento de lista es el bloque fundamental de la lista. Una vez que se crea el elemento de lista, puedes aprovecharlo para crear el componente de lista.

  1. Crea un método llamado AffirmationList(), anótalo con @Composable y declara un List de objetos Affirmation como parámetro en la firma del método.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>) {
}
  1. Declara un objeto modifier como parámetro en la firma del método con un valor predeterminado de Modifier.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
}
  1. En Jetpack Compose, se puede crear una lista desplazable con el elemento de componibilidad LazyColumn. La diferencia entre LazyColumn y Column es que debe usarse un objeto Column cuando tienes una pequeña cantidad de elementos para mostrar, ya que Compose los carga todos a la vez. Un Column solo puede contener una cantidad predefinida o fija de elementos de componibilidad. Un elemento LazyColumn puede agregar contenido a pedido, lo que lo hace útil para listas largas, en especial si no se conoce su longitud. Un LazyColumn también proporciona desplazamiento de manera predeterminada, sin código adicional. Declara un elemento LazyColumn de componibilidad dentro del método AffirmationList().

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
  }
}
  1. En el cuerpo de la lambda de LazyColumn, llama al método items() y pasa affirmationList. El método items() es la manera en la que agregas elementos a LazyColumn. Este método es algo único de ese elemento de componibilidad, y no se suele usar para la mayoría de los elementos de ese tipo.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){
    }
  }
}
  1. Una llamada al método items() requiere una función lambda. En esa función, especifica un parámetro de affirmation que represente un elemento de afirmación de affirmationList.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){ affirmation ->
    }
  }
}
  1. Para cada afirmación de la lista, llama al elemento componible AffirmationCard() y pásale la affirmation.

MainActivity.kt

@Composable
private fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
  LazyColumn {
    items(affirmationList){ affirmation ->
      AffirmationCard(affirmation)
    }
  }
}

Muestra la lista

  1. En la expresión lambda, llama al elemento de componibilidad AffirmationList y pasa DataSource().loadAffirmations() al parámetro affirmationList.

MainActivity.kt

@Composable
fun AffirmationApp() {
   AffirmationsTheme {
       Scaffold(
           content = {
               AffirmationList(affirmationList = Datasource().loadAffirmations())
           }
       )
   }
}

Ejecuta la app de Affirmations en un dispositivo o emulador y mira el producto terminado.

f6f09800b74f4700.png

5. Obtén el código de la solución

Si deseas ver el código de la solución, míralo en GitHub.

  1. Navega a la página de repositorio de GitHub del proyecto.
  2. Verifica que el nombre de la rama coincida con el especificado en el codelab. Por ejemplo, en la siguiente captura de pantalla, el nombre de la rama es main.

1e4c0d2c081a8fd2.png

  1. En la página de GitHub de este proyecto, haz clic en el botón Code, el cual abre una ventana emergente.

1debcf330fd04c7b.png

  1. En la ventana emergente, haz clic en el botón Download ZIP para guardar el proyecto en tu computadora. Espera a que se complete la descarga.
  2. Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
  3. Haz doble clic en el archivo ZIP para descomprimirlo. Se creará una carpeta nueva con los archivos del proyecto.

Abre el proyecto en Android Studio

  1. Inicia Android Studio.
  2. En la ventana Welcome to Android Studio, haz clic en Open.

d8e9dbdeafe9038a.png

Nota: Si Android Studio ya está abierto, selecciona la opción de menú File > Open.

8d1fda7396afe8e5.png

  1. En el navegador de archivos, ve hasta donde se encuentra la carpeta de proyecto descomprimido (probablemente en Descargas).
  2. Haz doble clic en la carpeta del proyecto.
  3. Espera a que Android Studio abra el proyecto.
  4. Haz clic en el botón Run 8de56cba7583251f.png para compilar y ejecutar la app. Asegúrate de que funcione como se espera.

6. Conclusión

Ahora sabes cómo crear tarjetas, elementos de lista y listas desplazables con Jetpack Compose. Ten en cuenta que estas son solo herramientas básicas para crear una lista. Puedes darle rienda suelta a tu creatividad y personalizar los elementos de la lista como quieras.

Resumen

  • Usa elementos de componibilidad Card para crear elementos de lista.
  • Modifica la IU que contiene un elemento de componibilidad Card.
  • Crea una lista desplazable con el elemento de componibilidad LazyColumn.
  • Crea una lista con elementos personalizados.