1. Antes de comenzar
En este codelab, agregarás imágenes de dados a tu app existente de Dice Roller para Android. Primero, asegúrate de completar el codelab anterior sobre la compilación base de la app de Dice Roller.
En lugar de mostrar el valor del lanzamiento del dado en un elemento TextView
, tu app mostrará la imagen del dado apropiada según la cantidad de caras que tenga el dado que se lance. Esto brindará a tu app una experiencia del usuario mucho más visual y mejorada.
Se te proporcionará un vínculo para que descargues las imágenes de dados, que agregarás como recursos en tu app. Para escribir el código de la imagen que se usará, deberás utilizar una sentencia when
en Kotlin.
Requisitos previos
- Haber completado el codelab Cómo crear una app interactiva de Dice Roller
- Capacidad de escribir sentencias de flujo de control (sentencias
if / else
,when
) - Capacidad de actualizar la IU de la app según la entrada del usuario (modificando el archivo
MainActivity.kt
) - Capacidad de agregar un objeto de escucha de clics a un
Button.
- Capacidad de agregar recursos de imagen a una app para Android
Qué aprenderás
- Cómo actualizar un elemento
ImageView
mientras la app se está ejecutando. - Cómo personalizar el comportamiento de tu app según las diferentes condiciones (mediante una sentencia
when
).
Qué compilarás
- Compilarás la app para Android de Dice Roller que tiene un
Button
para lanzar un dado y actualizar la imagen que se muestra en la pantalla.
Requisitos
- Una computadora que tenga Android Studio instalado
- Conexión a Internet para descargar las imágenes de los dados
2. Actualiza el diseño de la app
En esta tarea, reemplazarás el elemento TextView
de tu diseño por un elemento ImageView
que muestre una imagen del resultado del lanzamiento del dado.
Cómo abrir la app de Dice Roller
- Abre y ejecuta la app de Dice Roller desde el codelab anterior en Android Studio. Puedes usar el código de la solución o el que creaste.
La app debería verse de la siguiente manera:
- Abre
activity_main.xml
(app > res > layout > activity_main.xml). Se abrirá el editor de diseño.
Cómo borrar el elemento TextView
- En el editor de diseño, selecciona el elemento
TextView
en Component Tree.
- Haz clic con el botón derecho y selecciona Borrar o presiona la tecla
Delete
. - Por el momento, ignora la advertencia en el
Button
. Deberás corregir eso en el siguiente paso.
Cómo agregar un elemento ImageView al diseño
- Arrastra un elemento
ImageView
de Palette hasta la vista Design y colócalo sobre elButton
.
- En el diálogo Pick a Resource, selecciona avatars en Sample data. Esta es la imagen temporal que usarás hasta que agregues las imágenes de dados en la próxima tarea.
- Presiona OK. La vista Design de tu app debería verse de la siguiente manera:
- En Component Tree, verás dos errores. El elemento
Button
no tiene restricciones verticales, y el elementoImageView
, tampoco tiene restricciones verticales ni horizontales.
El Button
no tiene restricciones verticales porque quitaste el elemento TextView
debajo del que se encontraba en un principio. Ahora deberás colocar el elemento ImageView
y el Button
debajo de este.
Cómo posicionar los elementos ImageView y Button
Deberás centrar el elemento ImageView
de forma vertical en la pantalla, independientemente de dónde se ubique el Button
.
- Agrega restricciones horizontales a
ImageView
. Conecta el lado izquierdo del elementoImageView
al borde izquierdo delConstraintLayout
superior. - Conecta el lado derecho de
ImageView
al borde derecho del elemento superior. Esto centrará horizontalmente el elementoImageView
dentro del elemento superior.
- Agrega una restricción vertical a
ImageView
conectando la parte superior de laImageView
a la del elemento superior. LaImageView
se deslizará hacia arriba hasta la parte superior delConstraintLayout
.
- Agrega una restricción vertical a
Button
conectando la parte superior deButton
a la inferior deImageView
. ElButton
se deslizará hacia arriba hasta quedar debajo de laImageView
.
- Vuelve a seleccionar el elemento
ImageView
y agrega una restricción vertical que conecte la parte inferior deImageView
a la del elemento superior. Esto centrará el elementoImageView
en sentido vertical en elConstraintLayout
.
Deberían desaparecer todas las advertencias relativas a las restricciones.
Después de estos pasos, la vista Design debería verse así: ImageView
en el centro y Button
justo debajo.
Puede que veas una advertencia en el elemento ImageView
de Component Tree que indica que se debe agregar una descripción de contenido a tu ImageView
. Por el momento, no te preocupes por esta advertencia, ya que, más adelante en el codelab, establecerás la descripción de contenido de ImageView
según la imagen de dado que muestres. Este cambio se realizará en el código Kotlin.
3. Agrega las imágenes de dado
En esta tarea, descargarás algunas imágenes de dados y las agregarás a tu app.
Cómo descargar las imágenes de dados
- Abre esta URL para descargar en tu computadora un archivo ZIP con imágenes de dados. Espera a que se complete la descarga.
- Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
- Haz doble clic en el archivo ZIP para descomprimirlo. Se creará una carpeta
dice_images
nueva con los 6 archivos de imagen de dados, que muestran los valores de dado del 1 al 6.
Cómo agregar imágenes de dados a tu app
- En Android Studio, haz clic en View > Tool Windows > Resource Manager en los menús o en la pestaña Resource Manager, a la izquierda de la ventana Project.
- Haz clic en + debajo de Resource Manager y selecciona Import Drawables. Se abrirá un navegador de archivos.
- Busca y selecciona los 6 archivos de imagen de dados. Puedes seleccionar el primer archivo, mantener presionada la tecla
Shift
y, luego, seleccionar los otros archivos. - Haz clic en Open.
- Haz clic en Next y, luego, en Import para confirmar que deseas importar estos 6 recursos.
- Si los archivos se importaron con éxito, las 6 imágenes aparecerán en Resource Manager (app>res>drawable) de tu app.
¡Buen trabajo! En la próxima tarea, usarás estas imágenes en tu app.
Importante: Podrás consultar estas imágenes en tu código Kotlin mediante sus ID de recurso:
R.drawable.dice_1
R.drawable.dice_2
R.drawable.dice_3
R.drawable.dice_4
R.drawable.dice_5
R.drawable.dice_6
4. Usa las imágenes de dados
Cómo reemplazar la imagen de avatar de ejemplo
- En Design Editor, selecciona el elemento
ImageView
. - En Attributes, en la sección Declared Attributes, busca el atributo srcCompat de la herramienta, que se establece como la imagen de avatar.
Recuerda que el atributo srcCompat de la herramienta usa la imagen proporcionada solo dentro de la vista Design de Android Studio. La imagen solo se muestra a los desarrolladores mientras compilas la app, pero no se verá cuando la ejecutes en el emulador o en un dispositivo.
- Haz clic en la pequeña vista previa del avatar. Se abrirá un cuadro de diálogo a fin de seleccionar un nuevo recurso para que uses con esta
ImageView
.
- Selecciona el elemento de diseño
dice_1
y haz clic en OK.
¡Vaya! El elemento ImageView
ocupa toda la pantalla.
A continuación, ajusta el ancho y la altura del elemento ImageView
de modo que no oculte el Button
.
- En la ventana Attributes debajo del Constraints Widget, busca los atributos layout_width y layout_height. Su configuración actual es wrap_content, lo que significa que el elemento
ImageView
será tan alto y tan ancho como el contenido (la imagen de origen) dentro del mismo. - En su lugar, establece un ancho fijo de 160 dp y una altura fija de 200 dp en
ImageView
. Presiona Enter.
Ahora, ImageView
es mucho más pequeño.
Es posible que el Button
esté demasiado cerca de la imagen.
- Agrega un margen superior de 16 dp al botón. Configúralo en el Constraint Widget.
Cuando se actualice la vista Design, la app se verá mucho mejor.
Cómo cambiar la imagen del dado cuando se hace clic en el botón
Aunque se corrigió el diseño, debes actualizar la clase MainActivity
para usar las imágenes de dados.
En este momento, hay un error en la app, en el archivo MainActivity.kt
. Si intentas ejecutarla, verás el siguiente error de compilación:
Esto se debe a que tu código todavía hace referencia al elemento TextView
que borraste del diseño.
- Abre
MainActivity.kt
(app > java > com.example.diceroller > MainActivity.kt).
El código hace referencia al elemento R.id.textView
, pero Android Studio no lo reconoce.
- Dentro del método
rollDice()
, selecciona las porciones de código que hagan referencia al elementoTextView
y bórralas.
// Update the TextView with the dice roll
val resultTextView: TextView = findViewById(R.id.textView)
resultTextView.text = dice.roll().toString()
- Aún dentro de
rollDice()
, crea una nueva variable llamadadiceImage
de tipoImageView
. Configúrala igual que el elementoImageView
del diseño. Usa el métodofindViewById()
y pasa el ID de recurso paraImageView
,R.id.imageView
, como argumento de entrada.
val diceImage: ImageView = findViewById(R.id.imageView)
Si no sabes cómo determinar el ID de recurso exacto de ImageView
, verifica el ID ubicado en la parte superior de la ventana Atributos.
Cuando te refieras a este ID de recurso en el código Kotlin, asegúrate de escribirlo de forma exacta (con i minúscula, V mayúscula y sin espacios). De lo contrario, Android Studio mostrará un error.
- Agrega esta línea de código para probar que puedas actualizar correctamente el elemento
ImageView
cuando se hace clic en el botón. El lanzamiento del dado no siempre será "2", pero usa la imagendice_2
para hacer una prueba.
diceImage.setImageResource(R.drawable.dice_2)
Este código llama al método setImageResource()
de ImageView
y pasa el ID de recurso de la imagen dice_2
. Se actualizará la ImageView
en la pantalla para mostrar la imagen dice_2
.
El método rollDice() debería verse de la siguiente manera:
private fun rollDice() {
val dice = Dice(6)
val diceRoll = dice.roll()
val diceImage: ImageView = findViewById(R.id.imageView)
diceImage.setImageResource(R.drawable.dice_2)
}
- Ejecuta tu app para verificar que no se produzcan errores. La app debe iniciarse con una pantalla en blanco que solo contenga el botón Roll.
Cuando presiones el botón, aparecerá una imagen de dados que mostrará el valor 2. ¡Eso es!
Pudiste hacer que la imagen cambie luego de presionar el botón. ¡Estás cada vez más cerca!
5. Muestra la imagen del dado correcta en función del lanzamiento
Claramente, el resultado del lanzamiento del dado no siempre será un 2. Usa la lógica de flujo de control que aprendiste en el codelab Cómo agregar comportamiento condicional para diferentes lanzamientos de dados a fin de que en la pantalla se muestre la imagen de dado apropiada según el lanzamiento aleatorio.
Antes de comenzar a escribir código, piensa de manera conceptual en cómo se comportará la app y escribe pseudocódigo que describa lo que debería suceder. Por ejemplo:
Si el usuario lanza un 1, mostrar la imagen dice_1
.
Si el usuario lanza un 2, mostrar la imagen dice_2
.
Y así sucesivamente.
El pseudocódigo anterior se puede escribir con sentencias if / else
en Kotlin según el valor del dado.
if (diceRoll == 1) {
diceImage.setImageResource(R.drawable.dice_1)
} else if (diceRoll == 2) {
diceImage.setImageResource(R.drawable.dice_2)
}
...
Sin embargo, escribir if / else
para cada caso resulta bastante repetitivo. Se puede expresar la misma lógica de una forma más simple, con una sentencia when
. Esto resulta más conciso (requiere menos código). Usa este enfoque en tu aplicación.
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
...
Cómo actualizar el método rollDice()
- En el método
rollDice()
, borra la línea de código que establece el ID de recurso de la imagen siempre endice_2
.
diceImage.setImageResource(R.drawable.dice_2)
- Reemplázala por una sentencia
when
que actualice el elementoImageView
según el valor dediceRoll
.
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
Cuando termines de aplicar los cambios, el método rollDice()
debería verse de la siguiente manera:
private fun rollDice() {
val dice = Dice(6)
val diceRoll = dice.roll()
val diceImage: ImageView = findViewById(R.id.imageView)
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
}
- Ejecuta la app. Si haces clic en el botón Roll, la imagen del dado cambiará y mostrará un valor distinto de 2. ¡Funciona!
Cómo optimizar tu código
Si deseas escribir un código aún más conciso, puedes hacer el cambio que se muestra a continuación. No tiene ningún efecto visible para el usuario de tu app, pero el código será más corto y menos repetitivo.
Quizá notaste que la llamada a diceImage.setImageResource()
aparece 6 veces en tu sentencia when.
when (diceRoll) {
1 -> diceImage.setImageResource(R.drawable.dice_1)
2 -> diceImage.setImageResource(R.drawable.dice_2)
3 -> diceImage.setImageResource(R.drawable.dice_3)
4 -> diceImage.setImageResource(R.drawable.dice_4)
5 -> diceImage.setImageResource(R.drawable.dice_5)
6 -> diceImage.setImageResource(R.drawable.dice_6)
}
Lo único que cambia entre cada caso es el ID de recurso utilizado. Esto significa que puedes crear una variable para almacenar el ID de recurso que se usará. Luego, podrás llamar a diceImage.setImageResource()
una sola vez en tu código y pasar el ID de recurso correcto.
- Reemplaza el código anterior con el siguiente:
val drawableResource = when (diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
6 -> R.drawable.dice_6
}
diceImage.setImageResource(drawableResource)
Un concepto nuevo aquí es que una expresión when
en realidad puede mostrar un valor. Con este nuevo fragmento de código, la expresión when
muestra el ID de recurso correcto, que se almacenará en la variable drawableResource
. Podrás usar esa variable para actualizar el recurso de imagen que se mostrará.
- Ten en cuenta que
when
ahora está subrayada en color rojo. Si colocas el cursor sobre ella, verás un mensaje de error: la expresión "when" debe estar completa, agrega la rama "else" necesaria.
El error se da porque el valor de la expresión when
se asigna a drawableResource
, por lo que when
debe ser exhaustiva: debe manejar todos los casos posibles de forma que siempre se muestre un valor, incluso si cambias a un dado de 12 caras. Android Studio sugiere agregar una rama else
. Para solucionar este problema, cambia el caso de 6
a else
. Los casos del 1
al 5
son los mismos, pero else
administra todos los demás, incluido 6
.
val drawableResource = when (diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
diceImage.setImageResource(drawableResource)
- Ejecuta la app para comprobar que siga funcionando correctamente. Asegúrate de hacer suficientes pruebas a fin de asegurarte de que todos los números aparezcan con las imágenes de dado del 1 al 6.
Cómo establecer una descripción de contenido apropiada en el elemento ImageView
Ahora que reemplazaste el número lanzado por una imagen, los lectores de pantalla ya no podrán determinar qué número salió. Para solucionar este problema, después de actualizar el recurso de imagen, actualiza la descripción del contenido del elemento ImageView
. Esta debe ser una descripción de texto de lo que se muestra en el elemento ImageView
a fin de que los lectores de pantalla puedan describirlo.
diceImage.contentDescription = diceRoll.toString()
Los lectores de pantalla pueden leer en voz alta esta descripción de contenido. Por lo tanto, si en la pantalla se muestra la imagen del valor "6", la descripción de contenido se leerá en voz alta como "6".
6. Implementa las prácticas recomendadas de codificación
Cómo crear una experiencia de lanzamiento más útil
Cuando el usuario abre la app por primera vez, esta está en blanco (solo contiene el botón Roll), lo cual se ve extraño. Como es posible que los usuarios no sepan qué esperar, cambia la IU a fin de que muestre un lanzamiento de dado aleatorio cuando se inicie la app por primera vez y se cree el elemento Activity
. De esta forma, es más probable que los usuarios comprendan que, si presionan el botón Roll, se generará un lanzamiento del dado.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val rollButton: Button = findViewById(R.id.button)
rollButton.setOnClickListener { rollDice() }
// Do a dice roll when the app starts
rollDice()
}
Cómo agregar comentarios a tu código
Agrega algunos comentarios al código para describir lo que sucederá en virtud del código que escribiste.
Después de realizar todos estos cambios, así es cómo podría verse tu método rollDice()
:
/**
* Roll the dice and update the screen with the result.
*/
private fun rollDice() {
// Create new Dice object with 6 sides and roll the dice
val dice = Dice(6)
val diceRoll = dice.roll()
// Find the ImageView in the layout
val diceImage: ImageView = findViewById(R.id.imageView)
// Determine which drawable resource ID to use based on the dice roll
val drawableResource = when (diceRoll) {
1 -> R.drawable.dice_1
2 -> R.drawable.dice_2
3 -> R.drawable.dice_3
4 -> R.drawable.dice_4
5 -> R.drawable.dice_5
else -> R.drawable.dice_6
}
// Update the ImageView with the correct drawable resource ID
diceImage.setImageResource(drawableResource)
// Update the content description
diceImage.contentDescription = diceRoll.toString()
}
Para obtener el archivo MainActivity.kt
completo, consulta en GitHub el código de la solución vinculado en el siguiente paso.
Te felicitamos por completar la app de Dice Roller. ¡Ya puedes llevar esta app a la próxima noche de juegos con tus amigos!
7. Código de solución
El código de la solución para este codelab se encuentra en el proyecto y módulo que se muestran a continuación.
A fin de obtener el código necesario para este codelab y abrirlo en Android Studio, haz lo siguiente:
Obtén el código
- Haz clic en la URL proporcionada. Se abrirá la página de GitHub del proyecto en un navegador.
- En esa página, haz clic en el botón Code, que abre un cuadro de diálogo.
- En el cuadro de diálogo, haz clic en el botón Download ZIP para guardar el proyecto en tu computadora. Espera a que se complete la descarga.
- Ubica el archivo en tu computadora (probablemente en la carpeta Descargas).
- 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
- Inicia Android Studio.
- En la ventana Welcome to Android Studio, haz clic en Open an existing Android Studio project.
Nota: Si Android Studio ya está abierto, selecciona la opción de menú File > New > Import Project.
- En el cuadro de diálogo Import Project, navega hasta donde se encuentra la carpeta de proyecto descomprimido (probablemente en Descargas).
- Haz doble clic en la carpeta del proyecto.
- Espera a que Android Studio abra el proyecto.
- Haz clic en el botón Run para compilar y ejecutar la app. Asegúrate de que funcione como se espera.
- Explora los archivos del proyecto en la ventana de herramientas Project para ver cómo se configuró la app.
8. Resumen
- Usa
setImageResource()
para cambiar la imagen que se muestra en un elementoImageView
. - Usa sentencias de flujo de control, como expresiones
if / else
owhen
, a fin de manejar diferentes casos en tu app, por ejemplo, para mostrar imágenes distintas en circunstancias diferentes.
9. Más información
10. Practica por tu cuenta
Haz lo siguiente:
- Agrega otro dado a la app, de modo que un botón Roll muestre 2 resultados. ¿Cuántos
ImageViews
necesitarás en tu diseño? ¿Cómo afectará eso al códigoMainActivity.kt
?
Revisa tu trabajo
La app terminada debería ejecutarse sin errores y mostrar los dos dados.