Cómo mostrar una lista de imágenes con tarjetas

1. Antes de comenzar

En el codelab anterior, creaste una app de Affirmations que muestra una lista de texto en una RecyclerView.

7ac81c2a9a79365b.png

En este codelab de seguimiento, agregarás una imagen inspiradora a cada afirmación de tu app. Debes mostrar el texto y la imagen de cada afirmación dentro de una tarjeta con el widget MaterialCardView de la biblioteca de componentes de Material Design para Android. Luego, para terminar la app, perfeccionarás la IU a fin de crear una experiencia del usuario más coherente y atractiva. Esta es una captura de pantalla de la app completada:

8d7a20a5d7a079ce.png

Requisitos previos

  • Poder agregar recursos de imagen a una app.
  • Estar familiarizado con la modificación de un diseño XML.
  • Ser capaz de crear una app que muestre una lista de texto en un elemento RecyclerView
  • Ser capaz de crear un adaptador para un elemento RecyclerView

Qué aprenderás

  • Cómo agregar imágenes a la lista de afirmaciones que se muestran en un elemento RecyclerView.
  • Cómo usar el objeto MaterialCardView en el diseño de un elemento RecyclerView.
  • Cómo realizar cambios visuales en la IU para que la app luzca mejor.

Qué compilarás

  • Una app Affirmations mejorada que usa un elemento RecyclerView para mostrar una lista de tarjetas. Cada tarjeta contiene una imagen y un texto de afirmación.

Requisitos

  • Una computadora que tenga instalado Android Studio 4.1 o una versión posterior
  • Acceso a una conexión a Internet para descargar archivos de imagen
  • La app Affirmations del codelab anterior titulado Cómo crear una app Affirmations. (No se brinda código de partida. Crear la app es un requisito previo).

2. Agrega imágenes a los elementos de la lista

Hasta ahora, creaste un adaptador ItemAdapter para mostrar strings de afirmación en una RecyclerView. En términos funcionales, es óptimo; pero, en términos visuales, no es muy atractivo. En esta tarea, modificarás el diseño del elemento de la lista y el código del adaptador para mostrar imágenes con las afirmaciones.

Cómo descargar las imágenes

  1. Para comenzar, abre el proyecto de la app Affirmations en Android Studio desde el codelab anterior. Si no tienes este proyecto, repasa los pasos del codelab anterior para crear ese proyecto. Luego, regresa a este codelab.
  2. A continuación, descarga los archivos de imagen en tu computadora. Debería haber diez imágenes, una para cada afirmación de tu app. Los nombres de los archivos deben abarcar de image1.jpg a image10.jpg.
  3. Copia las imágenes de tu computadora en la carpeta res > drawable de tu proyecto (app/src/main/res/drawable) en Android Studio. Una vez que se agreguen estos recursos a tu app, podrás acceder a estas imágenes desde tu código con tus ID de recurso, como R.drawable.image1. (Es posible que debas volver a compilar tu código para que Android Studio encuentre la imagen).

Ya puedes usar las imágenes en la app.

Cómo agregar compatibilidad con imágenes en la clase Affirmation

En este paso, agregarás una propiedad en la clase de datos Affirmation a fin de conservar un valor para un ID de recurso de imagen. De esa manera, una sola instancia de objeto Affirmation contendrá un ID de recurso para el texto de la afirmación y un ID de recurso para la imagen de la afirmación.

  1. Abre el archivo Affirmation.kt dentro del paquete model.
  2. Para modificar el constructor de la clase Affirmation, agrega otro parámetro Int llamado imageResourceId.

Cómo usar anotaciones de recursos

Los dos elementos stringResourceId y imageResourceId son valores enteros. Si bien parece que está bien, el llamador podría pasar accidentalmente los argumentos en el orden incorrecto (primero imageResourceId en lugar de stringResourceId).

Para evitar esto, puedes usar las anotaciones de recursos. Las anotaciones son útiles porque agregan información adicional a las clases, los métodos o los parámetros. Las anotaciones siempre se declaran con un símbolo @. En este caso, agrega la anotación @StringRes a tu propiedad de ID del recurso de strings y la anotación @DrawableRes a tu propiedad de ID del recurso de elementos de diseño. Recibirás una advertencia si proporcionas el tipo de ID de recurso incorrecto.

  1. Agrega la anotación @StringRes a stringResourceId.
  2. Agrega la anotación @DrawableRes a imageResourceId.
  3. Asegúrate de que las importaciones androidx.annotation.DrawableRes y androidx.annotation.StringRes se agreguen en la parte superior de tu archivo después de la declaración del paquete.

Affirmation.kt

package com.example.affirmations.model

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes

data class Affirmation(
   @StringRes val stringResourceId: Int,
   @DrawableRes val imageResourceId: Int
)

Cómo inicializar la lista de afirmaciones con imágenes

Ahora que cambiaste el constructor de la clase Affirmation, debes actualizar la clase Datasource. Pasa un ID de recurso de imagen a cada objeto Affirmation que se inicialice.

  1. Abre Datasource.kt. Deberías ver un error para cada instancia de Affirmation.
  2. Para cada elemento Affirmation, agrega el ID de recurso de una imagen como argumento, por ejemplo, R.drawable.image1.

Datasource.kt

package com.example.affirmations.data

import com.example.affirmations.R
import com.example.affirmations.model.Affirmation

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)
        )
    }
}

Cómo agregar ImageView al diseño del elemento de la lista

Para mostrar una imagen por cada afirmación de tu lista, debes agregar un elemento ImageView al diseño del elemento. Como ahora tienes dos vistas (TextView y ImageView), debes ubicarlas como vistas secundarias dentro de un elemento ViewGroup. Para organizar las vistas en una columna vertical, puedes usar un elemento LinearLayout. LinearLayout alinea todas las vistas secundarias en una sola dirección, de manera vertical u horizontal.

a5cb4349a970c992.png

  1. Abre res > layout > list_item.xml. Agrega un elemento LinearLayout alrededor del objeto TextView existente y configura la propiedad orientation en vertical.
  2. Mueve la línea de declaración xmlns schema del elemento TextView al elemento LinearLayout para corregir el error.

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
  1. Dentro del elemento LinearLayout, antes de TextView,, agrega un objeto ImageView con un ID de recurso de item_image.
  2. Configura el ancho de ImageView en match_parent y la altura en 194dp. Según el tamaño de la pantalla, este valor debería mostrar algunas tarjetas en la pantalla en cualquier momento.
  3. Configura el elemento scaleType en centerCrop.
  4. Configura el atributo importantForAccessibility en no, ya que la imagen se usa con fines decorativos.
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="194dp"
        android:id="@+id/item_image"
        android:importantForAccessibility="no"
        android:scaleType="centerCrop" />

Cómo actualizar ItemAdapter para configurar la imagen

  1. Abre adapter/ItemAdapter.kt (app > java > adapter > ItemAdapter).
  2. Ve a la clase ItemViewHolder.
  3. Una instancia ItemViewHolder debe contener una referencia a TextView y una referencia a ImageView en el diseño del elemento de la lista. Realiza el siguiente cambio.

Debajo de la inicialización de la propiedad textView, agrega un elemento val llamado imageView. Usa findViewById() para buscar la referencia al objeto ImageView con el elemento item_image de ID y asígnalo a la propiedad imageView.

ItemAdapter.kt

class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view) {
    val textView: TextView = view.findViewById(R.id.item_title)
    val imageView: ImageView = view.findViewById(R.id.item_image)
}
  1. Busca la función onBindViewHolder() en ItemAdapter.
  2. Anteriormente, configuraste el elemento stringResourceId de la afirmación en textView, en el objeto ItemViewHolder. Ahora, configura el objeto imageResourceId del elemento de la afirmación en el parámetro ImageView de la vista de elementos de la lista.
    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = dataset[position]
        holder.textView.text = context.resources.getString(item.stringResourceId)
        holder.imageView.setImageResource(item.imageResourceId)
    }
  1. Ejecuta la app y desplázate por la lista de afirmaciones.

485d002900657409.png

¡La app parece mucho más atractiva con las imágenes! Sin embargo, todavía puedes mejorar la IU de la app. En la siguiente sección, realizarás ajustes pequeños en la app para mejorar la IU.

3. Perfecciona la IU

Hasta ahora, compilaste una app funcional que consiste en una lista de imágenes y strings de afirmaciones. En esta sección, verás cómo los cambios pequeños en el código y XML pueden lograr que la app luzca mejor.

Cómo agregar padding

Para comenzar, agrega algunos espacios en blanco entre los elementos de la lista.

  1. Abre item_list.xml (app > res > layout > item_list.xml) y agrega padding 16dp al elemento LinearLayout existente.

list_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">
  1. Agrega padding 16dp en el objeto item_title TextView.
  2. En el elemento TextView, configura el atributo textAppearance en ?attr/textAppearanceHeadline6. textAppearance es un atributo que te permite definir un estilo específico de texto. Para ver otros posibles valores de apariencia de texto predefinidos, consulta la sección TextAppearances en esta entrada de blog sobre atributos comunes del tema.
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:textAppearance="?attr/textAppearanceHeadline6" />
  1. Ejecuta la app. ¿Crees que la lista luce mejor?

a95304a44a8876d7.png

Cómo usar tarjetas

Es difícil determinar si una imagen pertenece al texto de la afirmación superior o inferior. Para corregir este problema, puedes usar una vista de tarjetas. La vista de tarjetas brinda una manera sencilla de incluir un grupo de vistas y, a la vez, proporciona un estilo coherente para el contenedor. Para obtener más orientación sobre el uso de tarjetas con Material Design, consulta esta guía sobre tarjetas.

  1. Agrega un elemento MaterialCardView alrededor del objeto LinearLayout existente.
  2. Una vez más, mueve la declaración del esquema de LinearLayout a MaterialCardView.
  3. Configura el elemento layout_width de MaterialCardView en match_parent y el objeto layout_height en wrap_content.
  4. Agrega un elemento layout_margin de 8dp.
  5. Quita el padding del objeto LinearLayout para que no tengas mucho espacio en blanco.
  6. Ahora, vuelve a ejecutar la app. ¿Puedes diferenciar mejor cada afirmación con MaterialCardView?

list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/item_image"
            android:layout_width="match_parent"
            android:layout_height="194dp"
            android:importantForAccessibility="no"
            android:scaleType="centerCrop" />

        <TextView
            android:id="@+id/item_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:textAppearance="?attr/textAppearanceHeadline6" />

    </LinearLayout>

</com.google.android.material.card.MaterialCardView>

af61b5d2baa66e39.png

Cómo cambiar los colores del tema de la app

Es posible que el color predeterminado del tema de la app no sea tan tranquilo como otras opciones que podrías elegir. En esta tarea, cambiarás el color del tema de la app a azul. Puedes volver a cambiarlo según tus propias ideas.

En este vínculo, puedes encontrar tonos predefinidos de azul de la paleta de colores de Material Design.

En este codelab, usarás los siguientes colores de la paleta de Material Design:

  • blue_200: #FF90CAF9
  • blue_500: #FF2196F3
  • blue_700: #FF1976D2

Cómo agregar recursos de color

Define los colores que se usan en tu app en un lugar centralizado: el archivo colors.xml.

  1. Abre colors.xml (res > values > colors.xml).
  2. Agrega nuevos recursos de color al archivo para los colores azules que se definen a continuación:
<color name="blue_200">#FF90CAF9</color>
<color name="blue_500">#FF2196F3</color>
<color name="blue_700">#FF1976D2</color>

Cómo cambiar los colores del tema

Ahora que tienes recursos nuevos de color, puedes utilizarlos en tu tema.

  1. Abre themes.xml (res > values > themes > themes.xml).
  2. Busca la sección <!-- Primary brand color. -->.
  3. Agrega o cambia colorPrimary para usar @color/blue_500.
  4. Agrega o cambia colorPrimaryVariant para usar @color/blue_700.
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item>
  1. Ejecuta la app. Deberías ver que el color de la barra de la app cambió y ahora es azul.

8d7a20a5d7a079ce.png

Cómo actualizar los colores del tema oscuro

Recomendamos que elijas más colores desaturados para el tema oscuro de la app.

  1. Abre el archivo themes.xml del tema oscuro (themes > themes.xml (night)).
  2. Agrega o cambia los atributos del tema colorPrimary y colorPrimaryVariant de la siguiente manera:
<item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_500</item>
  1. Ejecuta tu app.
  2. En la Configuración del dispositivo, activa el Tema oscuro.

  1. Tu app cambia al Tema oscuro. Verifica que se vea como en la siguiente captura de pantalla:

6564b21429206ebc.png

  1. En este punto, también puedes quitar los colores sin uso de tu archivo colors.xml (por ejemplo, los recursos de color púrpura que se usaron en el tema predeterminado de la app).

Cómo cambiar el ícono de la app

El último paso consiste en actualizar el ícono de la app.

  1. Descarga los archivos del ícono de la app ic_launcher_foreground.xml y ic_launcher_background.xml. Si tu navegador muestra el archivo en lugar de descargarlo, selecciona Archivo > Guardar página como… para guardarlo en tu computadora.
  2. En Android Studio, borra dos archivos: drawable/ic_launcher_background.xml y drawable-v24/ic_launcher_foreground.xml, ya que son para el ícono de la app anterior. Puedes desmarcar la casilla Safe delete (with usage search).
  3. Luego, haz clic con el botón derecho en la carpeta res > drawable y selecciona New > Image Asset.

51e40f30078ad631.png

  1. En la ventana Configure Image Asset, asegúrate de seleccionar Foreground layer.

8c437aa925887439.png

  1. Debajo, busca la etiqueta Path.
  2. Haz clic en el ícono de la carpeta dentro del cuadro de texto Path.
  3. Busca y abre el archivo ic_launcher_foreground.xml que descargaste en la computadora.

ddac89ef587fba99.png

  1. Cambia a la pestaña Background Layer.
  2. Haz clic en el ícono Browse, en el cuadro de texto Path.
  3. Busca y abre el archivo ic_launcher_background.xml en la computadora. No es necesario que hagas otros cambios.
  4. Haz clic en Next.

c0c1986d1887afdb.png

  1. En el diálogo Confirm Icon Path, haz clic en Finish. Está bien que reemplaces los íconos existentes.
  2. Como práctica recomendada, puedes mover los nuevos elementos de diseño vectorial ic_launcher_foreground.xml y ic_launcher_background.xml a un nuevo directorio de recursos llamado drawable-anydpi-v26. Los íconos adaptables se introdujeron en la API 26, por lo que estos recursos solo se usarán en dispositivos que ejecuten la API 26 y versiones posteriores (para cualquier dpi).
  3. Si ya no queda nada, borra el directorio drawable-v24.
  4. Ejecuta tu app y observa el hermoso ícono de esta en el panel de apps.

649133c325fa9b17.png

  1. Como último paso, no olvides volver a cambiar el formato de los archivos Kotlin y XML en el proyecto para que tu código sea más limpio y cumpla con los lineamientos de estilo.

¡Felicitaciones! Creaste una app Affirmations inspiradora.

Con este conocimiento sobre cómo mostrar una lista de datos en una app para Android, ¿qué puedes compilar en el futuro?

4. Código de solución

El código de solución para la app Affirmations se encuentra en el siguiente repositorio de 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 del proyecto descomprimida (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.

5. Resumen

  • Para mostrar contenido adicional en un elemento RecyclerView, modifica la clase del modelo de datos subyacente y la fuente de datos. Luego, actualiza el adaptador y el diseño del elemento de la lista para configurar esos datos en las vistas.
  • Usa las anotaciones de recursos para asegurarte de que el tipo de ID de recurso correcto se pase a un constructor de clase.
  • Usa la biblioteca de componentes de Material Design para Android de modo que tu app siga con mayor facilidad los lineamientos de Material Design.
  • Usa MaterialCardView para mostrar contenido en una tarjeta de Material.
  • Con algunos pequeños ajustes visuales en cuanto al color y los espacios, puedes lograr que la app luzca mejor y más coherente.

6. Más información

7. Tarea de desafío

En esta serie de codelabs, aprendiste cómo usar LinearLayoutManager con RecyclerView. RecyclerView puede usar diferentes LayoutManagers para diseñar datos de manera diferente.

  • Cambia la propiedad layoutManager del elemento RecyclerView a GridLayoutManager.
  • Cambia la cantidad de columnas a 3.
  • Cambia el diseño del adaptador para visualizar datos en una cuadrícula.