Intents y actividades

1. Introducción

Hasta ahora, las apps sobre las que trabajaste tuvieron una sola actividad. En realidad, muchas apps para Android requieren varias actividades y navegación entre ellas.

En este codelab, compilarás una app de diccionario de modo que utilice varias actividades, use intents para navegar entre ellas y pase los datos a otras apps.

Requisitos previos

Deberías ser capaz de hacer lo siguiente:

  • Navegar por un proyecto en Android Studio
  • Trabajar con recursos XML y agregarlos en Android Studio
  • Anular e implementar métodos en una clase existente
  • Crear instancias de clases de Kotlin, acceder a propiedades de clases y llamar a métodos
  • Consultar la documentación en developer.android.com para obtener más información acerca de las clases específicas

Qué aprenderás

Aprenderás a hacer lo siguiente:

  • Usar un intent explícito con el fin de navegar a una actividad específica
  • Usar un intent implícito a efectos de navegar al contenido de otra app
  • Agregar opciones de menú para agregar botones a la barra de la app.

Qué compilarás

  • Modifica una app de diccionario a fin de implementar la navegación entre pantallas mediante intents y agregar un menú de opciones.

Requisitos

  • Una computadora que tenga Android Studio instalado

2. Código de partida

En los próximos pasos, trabajarás con la app de Words. Esta es una app de diccionario simple que muestra una lista de letras y de palabras para cada letra, y tiene la capacidad de buscar definiciones de cada palabra en el navegador.

Puede que parezca mucho, pero no te preocupes: no tendrás que compilar una app completa para aprender sobre intents. En cambio, se te proporcionó una versión incompleta del proyecto, conocida como proyecto inicial.

Si bien todas las pantallas están implementadas, aún no puedes navegar de una a otra. Tu tarea es usar intents de modo que todo el proyecto funcione, sin tener que compilar todo desde cero.

Descarga el código de partida para este codelab

En este codelab, se brinda el código de partida para que lo extiendas con funciones que se explicarán aquí. El código de partida puede contener código que ya conoces de codelabs anteriores. También puede contener código que no te resulte conocido y que aprenderás en codelabs futuros.

Cuando descargues el código de partida de GitHub, ten en cuenta que el nombre de la carpeta es android-basics-kotlin-words-app-starter. Selecciona esta carpeta cuando abras el proyecto en Android Studio.

Si conoces los comandos de git, ten en cuenta que el código de partida se encuentra en una rama llamada "starter". Después de clonar el repositorio, revisa el código de la rama origin/starter. Si no usaste comandos de git previamente, sigue los pasos que se indican a continuación para descargar el código desde GitHub.

  1. Navega a la página provista del 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.

3. Descripción general de la app de Words

Antes de avanzar, tómate un momento para familiarizarte con el proyecto. Todos los conceptos deberían resultarte conocidos de la unidad anterior. En este momento, la app consta de dos actividades, cada una con una vista de reciclador y un adaptador.

61af34429128695e.png

Trabajarás en específico con los siguientes archivos:

  1. RecyclerView usa LetterAdapter en MainActivity. Cada letra es un botón con un onClickListener, que está vacío en este momento. Aquí es donde manejarás las presiones de los botones para navegar a la DetailActivity.
  2. RecyclerView usa WordAdapter en DetailActivity a efectos de mostrar una lista de palabras. Aunque aún no puedes navegar a esta pantalla, ten en cuenta que cada palabra también tiene un botón correspondiente con un onClickListener. Aquí agregarás código que vaya al navegador con el fin de mostrar una definición de la palabra.
  3. MainActivity también necesitará algunos cambios. Aquí implementarás el menú de opciones a efectos de mostrar un botón que permita a los usuarios alternar entre los diseños de lista y cuadrícula.

ce3474dba2a9c1c8.png

Cuando te sientas cómodo con el proyecto tal como está hasta ahora, continúa a la siguiente sección, en la que aprenderás sobre los intents.

4. Introducción a los intents

Ahora que configuraste el proyecto inicial, revisemos los intents y la forma en que puedes usarlos en tu app.

Un intent es un objeto que representa una acción que se realizará. El uso más común de un intent consiste en iniciar una actividad, aunque no es el único. Hay dos tipos de intents: implícito y explícito. Un intent explícito es muy específico y se usa cuando conoces la actividad precisa que se iniciará (a menudo, se trata de una pantalla en tu propia app).

Un intent implícito es un poco más abstracto y se usa para indicar al sistema el tipo de acción, como abrir un vínculo, redactar un correo electrónico o realizar una llamada telefónica, y el sistema es responsable de determinar la forma en que completará la solicitud. Es probable que hayas visto ambos tipos de intents en acción sin saberlo. En general, cuando muestras una actividad en tu propia app, usas un intent explícito.

Sin embargo, en el caso de las acciones que no necesariamente involucran la app actual (por ejemplo, si encontraste una página interesante de documentación de Android y deseas compartirla con amigos), deberás usar un intent implícito. Es posible que veas un menú como este en el que se pregunte qué app usar para compartir la página.

e9c77033d9224170.png

Usarás un intent explícito para realizar acciones o presentar pantallas en tu propia app y serás el responsable de todo el proceso. Por lo general, usas intents implícitos a fin de realizar acciones que involucran otras apps y que dependen del sistema a efectos de determinar el resultado final. Usarás ambos tipos de intents en la app de Words.

702236c6e2276f91.png

5. Configura el intent explícito

Es hora de implementar tu primer intent. En la primera pantalla, cuando el usuario presione una letra, se lo debe dirigir a una segunda pantalla con una lista de palabras. La DetailActivity ya está implementada, por lo que todo lo que se necesita es iniciarla mediante un intent. Como tu app sabe exactamente qué actividad se debe iniciar, utilizarás un intent explícito.

Para crear y usar un intent, solo necesitas seguir algunos pasos:

  1. Abre LetterAdapter.kt y desplázate hacia abajo hasta onBindViewHolder(). Debajo de la línea para configurar el texto del botón, establece el onClickListener en holder.button.
holder.button.setOnClickListener {

}
  1. Luego, obtén una referencia al context.
val context = holder.itemView.context
  1. Crea un Intent y pasa el contexto y el nombre de clase de la actividad de destino.
val intent = Intent(context, DetailActivity::class.java)

El nombre de la actividad que deseas mostrar se especifica con DetailActivity::class.java. Se creará un objeto DetailActivity en segundo plano.

  1. Llama al método putExtra. Pasa "letter" como primer argumento y el texto del botón como el segundo.
intent.putExtra("letter", holder.button.text.toString())

¿Qué es un extra? Recuerda que un intent es solo un conjunto de instrucciones: todavía no hay una instancia de la actividad de destino. En cambio, un extra es un dato al que se le asigna un nombre que se puede recuperar más adelante, como un número o una cadena. Esto es similar a pasar un argumento cuando llamas a una función. Dado que se puede mostrar una DetailActivity para cualquier letra, debes indicarle cuál letra presentar.

Además, ¿por qué crees que es necesario llamar a toString()? El texto del botón ya es una cadena, ¿no?

Más o menos. En realidad, es de tipo CharSequence, que es algo denominado interfaz. Por ahora, no necesitas obtener más información sobre las interfaces de Kotlin, excepto que son una forma de garantizar que un tipo, como String, implemente funciones y propiedades específicas. Puedes pensar en una CharSequence como una representación más genérica de una clase similar a una cadena. La propiedad text de un botón puede ser una cadena o cualquier objeto que también sea una CharSequence. Sin embargo, el método putExtra() acepta una String, no solo cualquier CharSequence, por lo que es necesario llamar a toString().

  1. Llama al método startActivity() en el objeto de contexto y pasa el intent.
context.startActivity(intent)

Ahora ejecuta la app y presiona una letra. Se mostrará la pantalla de detalles. No obstante, independientemente de la letra que presione el usuario, la pantalla de detalles siempre mostrará las palabras que comienzan con la letra A. Aún debes trabajar sobre algunas cosas en la actividad de los detalles de modo que aparezcan las palabras correspondientes a la letra que se pase como el intent extra.

6. Configura DetailActivity

Acabas de crear tu primer intent explícito. Ahora, continuemos con la pantalla de detalles.

En el método onCreate de DetailActivity, después de la llamada a setContentView, reemplaza la letra hard-coded con el código que obtenga el letterId que se pasó desde el intent.

val letterId = intent?.extras?.getString("letter").toString()

Veamos cada parte de todo lo que está ocurriendo:

En primer lugar, ¿de dónde proviene la propiedad intent? No es una propiedad de DetailActivity, sino una propiedad de cualquier actividad. Mantiene una referencia al intent utilizado a efectos de iniciar la actividad.

La propiedad extras es de tipo Bundle y, como imaginarás, brinda una forma de acceder a todos los extras pasados al intent.

Ambas propiedades están marcadas con un signo de interrogación. ¿A qué se debe? El motivo es que las propiedades intent y extras admiten valores nulos, lo cual significa que pueden tener un valor o no tenerlo. A veces, quizás necesites que una variable sea null. Es posible que la propiedad intent en realidad no sea un Intent (si la actividad no se inició a partir de un intent) y que la propiedad extras no sea un Bundle, sino un valor llamado null. En Kotlin, null significa la ausencia de un valor. El objeto puede existir o ser null. Si tu app intenta acceder a una propiedad o llama a una función en un objeto null, fallará. Para acceder de forma segura a este valor, coloca un ? después del nombre. Si intent es null, tu app no intentará acceder a la propiedad extras; si extras es nulo, el código no intentará llamar a getString().

¿Cómo sabes qué propiedades requieren un signo de interrogación para garantizar la seguridad nula? Puedes confirmarlo si el nombre del tipo va seguido de un signo de interrogación o de exclamación.

b43155b06a5556e.png

El último paso que debes tener en cuenta es que la letra se recupera con getString, que muestra una String?, por lo que se llama a toString() a fin de garantizar que sea una String y no null.

Ahora, cuando ejecutes la app y navegues a la pantalla de detalles, deberías ver la lista de palabras correspondiente a cada letra.

c465ef280fe3792a.png

Limpieza

Tanto el código para realizar el intent como el utilizado a fin de recuperar la letra seleccionada codifican el nombre del extra, "letter". Si bien esto funciona en este pequeño ejemplo, no es el mejor enfoque en apps de gran tamaño en las que tienes muchos más extras de intents para controlar.

Aunque podrías crear una constante llamada "letter", esto podría hacerse difícil de manejar a medida que agregues más extras de intents a tu app. ¿En qué clase colocarías esta constante? Recuerda que se usa la cadena tanto en DetailActivity como en MainActivity. Necesitas una forma de definir una constante que pueda usarse en varias clases sin que se desorganice tu código.

Afortunadamente, hay una práctica función de Kotlin que se puede usar para separar las constantes y permitir que se puedan usar sin una instancia en particular de la clase llamada objetos complementarios. Un objeto complementario es similar a otros objetos, como las instancias de una clase. Sin embargo, solo habrá una única instancia de un objeto complementario durante el programa, por lo que a veces recibe el nombre de patrón de singleton. Si bien hay numerosos casos de uso para singletons más allá del alcance de este codelab, por ahora, usarás un objeto complementario como una manera de organizar las constantes y hacerlas accesibles fuera de la DetailActivity. Comenzarás usando un objeto complementario para refactorizar el código para el extra de "letter".

  1. En DetailActivity, justo encima de onCreate, agrega lo siguiente:
companion object {

}

Ten en cuenta que esto es similar a definir una clase, excepto que usas la palabra clave object. También existe una palabra clave companion, lo que significa que está asociada con la clase DetailActivity, y no necesitamos asignarle un nombre de tipo diferente.

  1. Dentro de llaves, agrega una propiedad para la constante de la letra.
const val LETTER = "letter"
  1. Para usar la nueva constante, actualiza la llamada a la letra hard-coded en onCreate() de la siguiente manera:
val letterId = intent?.extras?.getString(LETTER).toString()

Nuevamente, observa que haces referencia a esto con la notación de puntos habitual, pero la constante pertenece a DetailActivity.

  1. Cambia a LetterAdapter y modifica la llamada a putExtra para usar la nueva constante.
intent.putExtra(DetailActivity.LETTER, holder.button.text.toString())

Todo listo Con la refactorización, acabas de hacer que tu código sea más fácil de leer y de mantener. Si esta constante (o cualquier otra que agregues) necesita cambiar, solo deberás hacerlo en un solo lugar.

Para obtener más información acerca de los objetos complementarios, consulta la documentación de Kotlin sobre expresiones y declaraciones de objetos.

7. Configura el intent implícito

En la mayoría de los casos, presentarás actividades específicas de tu propia app. Sin embargo, hay algunas situaciones en las que es posible que no sepas qué actividad o qué app quieres iniciar. En nuestra pantalla de detalles, cada palabra es un botón que mostrará la definición de la palabra al usuario.

En nuestro ejemplo, usarás la funcionalidad del diccionario que ofrece una búsqueda de Google. No obstante, en lugar de agregar una nueva actividad a tu app, iniciarás el navegador del dispositivo de modo que muestre la página de búsqueda.

Por lo tanto, tal vez necesites un intent a fin de cargar la página en Chrome, el navegador predeterminado en Android, ¿verdad?

No exactamente.

Es posible que algunos usuarios prefieran un navegador de terceros. O que su teléfono venga con un navegador preinstalado por el fabricante. Tal vez tengan la app de Búsqueda de Google instalada o incluso una app de diccionario de terceros.

No sabes con certeza qué apps instaló el usuario. Tampoco puedes asumir la forma en la que quieren buscar una palabra. Este es un ejemplo perfecto de cuándo se debe usar un intent implícito. Tu app brinda información al sistema sobre la acción que se debe ejecutar, y el sistema determina qué hacer con esa acción y le solicita al usuario información adicional según sea necesario.

Para crear un intent implícito, haz lo siguiente:

  1. Para esta app, realizarás una búsqueda de la palabra en Google. El primer resultado de la búsqueda será una definición de diccionario de la palabra. Debido a que se usa la misma URL base para cada búsqueda, te recomendamos que la definas como su propia constante. En DetailActivity, modifica el objeto complementario a fin de agregar una nueva constante, SEARCH_PREFIX. Esta es la URL base de una búsqueda en Google.
companion object {
   const val LETTER = "letter"
   const val SEARCH_PREFIX = "https://www.google.com/search?q="
}
  1. Luego, abre WordAdapter y, en el método onBindViewHolder(), llama a setOnClickListener() en el botón. Primero, crea un Uri para la búsqueda. Cuando llamas a parse() con el fin de crear un Uri desde una String, debes usar el formato de cadena de modo que la palabra se agregue al SEARCH_PREFIX.
holder.button.setOnClickListener {
    val queryUrl: Uri = Uri.parse("${DetailActivity.SEARCH_PREFIX}${item}")
}

Si te preguntas qué es un URI, no es un error tipográfico, sino un identificador uniforme de recursos. Es posible que sepas que una URL, o localizador uniforme de recursos, es una cadena que apunta a una página web. Un URI es un término más general para el formato. Todas las URLs son URIs, pero no todos los URIs son URLs. Otros URIs (por ejemplo, una dirección relacionada con un número de teléfono), comenzarán con tel:, pero estos se consideran URN o nombres uniformes de recursos y no URL. El tipo de datos que se usa para representar ambos se denomina URI.

828cef3fdcfdaed.png

Observa que aquí no se hace referencia a ninguna actividad de tu app. Simplemente, debes proporcionar un URI, sin indicar cómo se usará en última instancia.

  1. Después de definir queryUrl, inicializa un nuevo objeto intent.
val intent = Intent(Intent.ACTION_VIEW, queryUrl)

En lugar de pasar un contexto y una actividad, pasas Intent.ACTION_VIEW junto con el URI.

ACTION_VIEW es un intent genérico que recibe un URI, en tu caso, una dirección web. Luego, el sistema sabrá que debe procesar este intent abriendo el URI en el navegador web del usuario. Entre otros tipos de intents, se incluyen los siguientes:

  • CATEGORY_APP_MAPS: Inicia la app de mapas.
  • CATEGORY_APP_EMAIL: Inicia la app de correo electrónico.
  • CATEGORY_APP_GALLERY: Inicia la app de la galería (fotos).
  • ACTION_SET_ALARM: Establece una alarma en segundo plano.
  • ACTION_DIAL: Inicia una llamada telefónica.

Para obtener más información, consulta la documentación sobre algunos intents de uso frecuente.

  1. Por último, aunque no inicies una actividad en particular en tu app, puedes indicar al sistema que inicie otra app llamando a startActivity() y pasando intent.
context.startActivity(intent)

Ahora, cuando inicies la app, navegues a la lista de palabras y presiones una de las palabras, tu dispositivo debería navegar a la URL (o presentar una lista de opciones en función de las apps instaladas).

El comportamiento exacto será distinto entre los usuarios, lo que brindará una experiencia fluida para todos, sin necesidad de complicar tu código.

8. Configura los íconos y el menú

Ahora que agregaste los intents implícitos y explícitos de modo que tu app sea completamente navegable, es hora de agregar una opción de menú a fin de que el usuario pueda alternar entre los diseños de lista y cuadrícula para las letras.

Es probable que hayas notado que varias apps tienen una barra en la parte superior de la pantalla. Esta se denomina barra de la app y, además de mostrar el nombre de la app, se puede personalizar y puede contener muchas funcionalidades útiles, como accesos directos a acciones útiles o menús ampliados.

dfc4095251c1466e.png

En esta app, no agregaremos un menú completo, pero aprenderás a agregar un botón personalizado a la barra de la app de modo que el usuario pueda cambiar el diseño.

  1. En primer lugar, debes importar dos íconos que representen las vistas de cuadrícula y de lista. Agrega los elementos vectoriales de imágenes prediseñadas llamados "módulo de vistas" (nómbralo ic_grid_layout) y "lista de vistas" (nómbralo ic_linear_layout). Si necesitas repasar la forma de agregar íconos de material, consulta las instrucciones que se encuentran en esta página.

5a01fc03113ac399.png

  1. También necesitas una manera de indicarle al sistema qué opciones se muestran en la barra de la app y qué íconos usar. Para ello, agrega un nuevo archivo de recursos haciendo clic con el botón derecho en la carpeta res y seleccionando New > Android Resource File. Establece el Resource Type en Menu y el File Name en layout_menu.

c4f83806a1aa121b.png

  1. Haz clic en OK.
  2. Abre res/Menu/layout_menu. Reemplaza el contenido de layout_menu.xml con lo siguiente:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item android:id="@+id/action_switch_layout"
       android:title="@string/action_switch_layout"
       android:icon="@drawable/ic_linear_layout"
       app:showAsAction="always" />
</menu>

La estructura del archivo de menú es bastante simple. Al igual que un diseño comienza con un administrador de diseño para retener vistas individuales, un archivo de menú en formato XML comienza con una etiqueta de menú que contiene opciones individuales.

Tu menú solamente tiene un botón y algunas propiedades:

  • id: Al igual que las vistas, la opción de menú tiene un ID de modo que se pueda hacer referencia a ella en el código.
  • title: En este caso, este texto no será visible, pero podría ser útil para que los lectores de pantalla identifiquen el menú.
  • icon: El valor predeterminado es ic_linear_layout. Sin embargo, esta opción se activará y desactivará para mostrar el ícono de cuadrícula cuando se seleccione el botón.
  • showAsAction: Indica al sistema cómo mostrar el botón. Como está configurado para que siempre se muestre, este botón siempre estará visible en la barra de la app y no se incluirá en un menú ampliado.

Por supuesto, el hecho de tener la configuración de propiedades no implica que el menú en realidad haga algo.

Deberás agregar código a MainActivity.kt de modo que el menú funcione.

9. Implementa el Botón de menú

Para ver el botón de menú en acción, debes realizar algunas acciones en MainActivity.kt.

  1. En primer lugar, es recomendable crear una propiedad para realizar un seguimiento del estado de diseño en el que se encuentra la app. De este modo, será más fácil activar o desactivar el botón de diseño. Establece el valor predeterminado en true, ya que el administrador de diseño lineal se usará de forma predeterminada.
private var isLinearLayoutManager = true
  1. Cuando el usuario active el botón, querrás que la lista de elementos se convierta en una cuadrícula de elementos. Según lo que aprendiste acerca de las vistas de reciclador, recordarás que hay muchos administradores de diseño diferentes, uno de los cuales (GridLayoutManager) admite varios elementos en una misma fila.
private fun chooseLayout() {
    if (isLinearLayoutManager) {
        recyclerView.layoutManager = LinearLayoutManager(this)
    } else {
        recyclerView.layoutManager = GridLayoutManager(this, 4)
    }
    recyclerView.adapter = LetterAdapter()
}

Aquí, se usa una sentencia if con el fin de asignar el administrador de diseño. Además de configurar el layoutManager, este código también asigna el adaptador. LetterAdapter se usa tanto en los diseños de lista como en los de cuadrícula.

  1. Cuando configuraste el menú por primera vez en XML, le diste un ícono estático. Sin embargo, después de activar o desactivar el diseño, debes actualizar el ícono de modo que este refleje su nueva función: regresar al diseño de lista. Aquí, simplemente, establece los íconos de diseño lineal y de cuadrícula, según el diseño al que volverá el botón la próxima vez que se presione.
private fun setIcon(menuItem: MenuItem?) {
   if (menuItem == null)
       return

   // Set the drawable for the menu icon based on which LayoutManager is currently in use

   // An if-clause can be used on the right side of an assignment if all paths return a value.
   // The following code is equivalent to
   // if (isLinearLayoutManager)
   //     menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
   // else menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
   menuItem.icon =
       if (isLinearLayoutManager)
           ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
       else ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
}

El ícono se configura de forma condicional en función de la propiedad isLinearLayoutManager.

Para que tu aplicación realmente use el menú, deberás anular dos métodos más.

  • onCreateOptionsMenu: Con él, aumentas el menú de opciones y realizas cualquier configuración adicional.
  • onOptionsItemSelected: Con él, llamarás a chooseLayout() cuando se seleccione el botón.
  1. Anula onCreateOptionsMenu de la siguiente manera:
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   menuInflater.inflate(R.menu.layout_menu, menu)

   val layoutButton = menu?.findItem(R.id.action_switch_layout)
   // Calls code to set the icon based on the LinearLayoutManager of the RecyclerView
   setIcon(layoutButton)

   return true
}

Aquí no hay nada sofisticado. Después de aumentar el diseño, llama a setIcon() a fin de asegurarte de que el ícono sea correcto en función del diseño. El método muestra un Boolean: muestra true aquí, ya que quieres que se cree el menú de opciones.

  1. Implementa onOptionsItemSelected como se indica, con solo unas pocas líneas de código.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
   return when (item.itemId) {
       R.id.action_switch_layout -> {
           // Sets isLinearLayoutManager (a Boolean) to the opposite value
           isLinearLayoutManager = !isLinearLayoutManager
           // Sets layout and icon
           chooseLayout()
           setIcon(item)

           return true
       }
       //  Otherwise, do nothing and use the core event handling

       // when clauses require that all possible paths be accounted for explicitly,
       //  for instance both the true and false cases if the value is a Boolean,
       //  or an else to catch all unhandled cases.
       else -> super.onOptionsItemSelected(item)
   }
}

Se llamará a este método cada vez que se presione un elemento de menú, por lo que debes asegurarte de comprobar qué elemento se presionó. Usa una sentencia when, arriba. Si el id coincide con el elemento de menú action_switch_layout, el valor de isLinearLayoutManager será negativo. Luego, llama a chooseLayout() y setIcon() para actualizar la IU según corresponda.

Veamos una última cosa antes de que ejecutes la app. Debido a que el administrador de diseño y el adaptador ahora están configurados en chooseLayout(), debes reemplazar ese código en onCreate() para llamar a tu nuevo método. onCreate() debería verse de la siguiente manera después del cambio.

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)

   val binding = ActivityMainBinding.inflate(layoutInflater)
   setContentView(binding.root)

   recyclerView = binding.recyclerView
   // Sets the LinearLayoutManager of the recyclerview
   chooseLayout()
}

Ahora ejecuta tu app. Deberías poder alternar entre las vistas de lista y de cuadrícula mediante el botón de menú.

10. Código de solución

El código de solución para este codelab se encuentra en el proyecto que se muestra a continuación:

  1. Navega a la página provista del 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 compile como se espera.

11. Resumen

  • Los intents explícitos se usan para navegar a actividades específicas en tu app.
  • Los intents implícitos corresponden a acciones específicas (como abrir un vínculo o compartir una imagen) y permiten que el sistema determine cómo completar el intent.
  • Las opciones de menú te permiten agregar botones y menús a la barra de la app.
  • Los objetos complementarios proporcionan una manera de asociar constantes reutilizables a un tipo en lugar de hacerlo a una instancia de ese tipo.

Para realizar un intent, sigue estos pasos:

  • Obtén una referencia al contexto.
  • Crea un objeto Intent que proporcione una actividad o un tipo de intent (en función de si es explícito o implícito).
  • Llama a putExtra() para pasar los datos necesarios.
  • Llama a startActivity() y pasa el objeto intent.

12. Más información