Aspectos básicos de Kotlin para Android 10.3: Diseño para todos

Este codelab es parte del curso Conceptos básicos de Kotlin para Android. Aprovecharás al máximo este curso si trabajas con los codelabs de forma secuencial. Todos los codelabs del curso se enumeran en la página de destino de los codelabs de Android Kotlin Fundamentals.

Introducción

Crear una app que sea utilizable para la mayor cantidad de usuarios tiene sentido, ya sea que la desarrolles por placer o con fines comerciales. Hay varias dimensiones para lograrlo.

  • Compatibilidad con idiomas RTL. El inglés y muchos otros idiomas se leen de izquierda a derecha, y las apps que se originan en esas configuraciones regionales suelen diseñarse para que se adapten bien a esos idiomas. Muchos otros idiomas con una gran cantidad de hablantes se leen de derecha a izquierda, como el árabe. Haz que tu app funcione con idiomas de derecha a izquierda (RTL) para aumentar tu público potencial.
  • Realiza un análisis de accesibilidad. Adivinar cómo otra persona puede experimentar tu app es una opción con inconvenientes. La app de la Prueba de accesibilidad elimina las conjeturas del proceso y analiza tu app para identificar dónde podrías mejorar su accesibilidad.
  • Diseña para TalkBack con descripciones de contenido. Las discapacidades visuales son más comunes de lo que se cree, y muchos usuarios, no solo los ciegos, usan un lector de pantalla. Las descripciones de contenido son frases que un lector de pantalla dice cuando un usuario interactúa con un elemento de la pantalla.
  • Compatibilidad con el modo nocturno Para muchos usuarios con discapacidad visual, cambiar los colores de la pantalla mejora el contraste y los ayuda a trabajar visualmente con tu app. Android facilita la compatibilidad con el modo oscuro, y siempre debes admitir el modo oscuro para brindarles a los usuarios una alternativa simple a los colores de pantalla predeterminados.

En este codelab, explorarás cada una de estas opciones y agregarás compatibilidad con ellas a la app de GDG Finder.

También aprenderás a usar chips con tu app para Android, que puedes usar para hacer que tu app sea más interesante y, al mismo tiempo, mantenerla accesible.

Conocimientos que ya deberías tener

Debes estar familiarizado con lo siguiente:

  • Cómo crear apps que tengan actividades y fragmentos, y navegar entre fragmentos pasando datos
  • Usar vistas y grupos de vistas para diseñar una interfaz de usuario, en particular, RecyclerView
  • Cómo usar los componentes de arquitectura, incluido ViewModel, con la arquitectura recomendada para crear una app eficiente y bien estructurada
  • Vinculación de datos, corrutinas y cómo controlar los clics del mouse
  • Cómo conectarse a Internet y almacenar datos en caché de forma local con una base de datos de Room
  • Cómo establecer propiedades de la vista y cómo extraer recursos en archivos de recursos XML y usarlos desde ellos
  • Cómo usar estilos y temas para personalizar la apariencia de tu app
  • Cómo usar componentes de Material, recursos de dimensiones y colores personalizados

Qué aprenderás

  • Cómo hacer que tu app pueda ser usada por la mayor cantidad de usuarios
  • Cómo hacer que tu app funcione para idiomas de derecha a izquierda (RTL)
  • Cómo evaluar la accesibilidad de tu app
  • Cómo usar las descripciones de contenido para que tu app funcione mejor con los lectores de pantalla
  • Cómo usar chips
  • Cómo hacer que tu app funcione con el modo oscuro

Actividades

  • Evaluar y extender una app determinada para mejorar la accesibilidad haciendo que funcione para idiomas con escritura de derecha a izquierda
  • Analiza tu app para determinar dónde se podría mejorar la accesibilidad.
  • Usa descripciones de contenido para las imágenes.
  • Aprende a usar elementos de diseño.
  • Agrega la capacidad de usar el modo nocturno a tu app.

La app de inicio de GDG-finder se basa en todo lo que aprendiste hasta ahora en este curso.

La app usa ConstraintLayout para diseñar tres pantallas. Dos de las pantallas son solo archivos de diseño que usarás para explorar los colores y el texto en Android.

La tercera pantalla es un buscador de GDG. Los GDG, o Grupos de Google Developers, son comunidades de desarrolladores que se enfocan en las tecnologías de Google, incluido Android. Los GDG de todo el mundo organizan reuniones, conferencias, Study Jams y otros eventos.

A medida que desarrolles esta app, trabajarás en la lista real de GDG. La pantalla del buscador usa la ubicación del dispositivo para ordenar los GDG por distancia.

Si tienes suerte y hay un GDG en tu región, puedes visitar el sitio web y registrarte para asistir a sus eventos. Los eventos de GDG son una excelente manera de conocer a otros desarrolladores de Android y aprender las prácticas recomendadas de la industria que no se incluyeron en este curso.

En las siguientes capturas de pantalla, se muestra cómo cambiará tu app desde el comienzo hasta el final de este codelab.

La principal diferencia entre los idiomas de izquierda a derecha (LTR) y de derecha a izquierda (RTL) es la dirección del contenido que se muestra. Cuando se cambia la dirección de la IU de LTR a RTL (o viceversa), a menudo se denomina duplicación. La duplicación afecta a la mayor parte de la pantalla, incluidos el texto, los íconos de los campos de texto, los diseños y los íconos con indicaciones (como las flechas). Otros elementos no se reflejan, como los números (reloj, números de teléfono), los íconos que no tienen dirección (modo de avión, Wi-Fi), los controles de reproducción y la mayoría de los gráficos.

Más de mil millones de personas en todo el mundo usan idiomas que se escriben de derecha a izquierda. Los desarrolladores de Android se encuentran en todo el mundo, por lo que una app de GDG Finder debe admitir idiomas con escritura de derecha a izquierda.

Paso 1: Agrega compatibilidad con RTL

En este paso, harás que la app de GDG Finder funcione con idiomas RTL.

  1. Descarga y ejecuta la app de GDGFinderMaterial, que es la app de inicio para este codelab, o bien continúa desde el código final del codelab anterior.
  2. Abre el manifiesto de Android.
  3. En la sección <application>, agrega el siguiente código para especificar que la app admite RTL.
<application
        ...
        android:supportsRtl="true">
  1. Abre activity_main.xml en la pestaña Design.
  2. En el menú desplegable Configuración regional para la vista previa, elige Vista previa de derecha a izquierda. (Si no encuentras este menú, amplía el panel o cierra el panel Atributos para descubrirlo).

  1. En la vista previa, observa que el encabezado "GDG Finder" se movió hacia la derecha y que el resto de la pantalla permanece casi igual. En general, esta pantalla es aceptable. Sin embargo, la alineación en la vista de texto ahora es incorrecta, ya que está alineada a la izquierda en lugar de a la derecha.

  1. Para que esto funcione en tu dispositivo, en la Configuración del dispositivo o emulador, en Opciones para desarrolladores, selecciona Forzar diseño der. a izq.. (Si necesitas activar las Opciones para desarrolladores, busca el Número de compilación y haz clic en él hasta que aparezca un mensaje que indique que eres desarrollador. Esto varía según el dispositivo y la versión del sistema Android.

  1. Ejecuta la app y verifica en el dispositivo que la pantalla principal se vea igual que en la Vista previa. Observa que el FAB ahora se encuentra a la izquierda y el menú de hamburguesa a la derecha.
  2. En la app, abre el panel lateral de navegación y ve a la pantalla Search. Como se muestra a continuación, los íconos siguen a la izquierda y no se ve ningún texto. Resulta que el texto está fuera de la pantalla, a la izquierda del ícono. Esto se debe a que el código usa referencias de pantalla izquierda o derecha en las propiedades de la vista y las restricciones de diseño.

Paso 2: Usa start y end en lugar de left y right

"Izquierda" y "derecha" en la pantalla (cuando miras la pantalla) no cambian, incluso si cambia la dirección del texto. Por ejemplo, layout_constraintLeft_toLeftOf siempre restringe el lado izquierdo del elemento al lado izquierdo de la pantalla. En el caso de tu app, el texto está fuera de la pantalla en los idiomas RTL, como se muestra en la captura de pantalla anterior.

Para solucionar este problema, en lugar de "izquierda" y "derecha", usa la terminología de Start y End. Esta terminología establece el inicio y el final del texto de forma adecuada para la dirección del texto en el idioma actual, de modo que los márgenes y los diseños se encuentren en las áreas correctas de las pantallas.

  1. Open list_item.xml.
  2. Reemplaza las referencias a Left y Right por referencias a Start y End.
app:layout_constraintStart_toStartOf="parent"

app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
  1. Reemplaza el layout_marginLeft de ImageView por layout_marginStart. Esto mueve el margen al lugar correcto para alejar el ícono del borde de la pantalla.
<ImageView
android:layout_marginStart="
?
  1. Abre fragment_gdg_list.xml. Consulta la lista de GDG en el panel Vista previa. Observa que el ícono sigue apuntando en la dirección incorrecta porque está invertido (si el ícono no está invertido, asegúrate de que sigues viendo la vista previa de derecha a izquierda). Según los lineamientos de Material Design, los íconos no deben reflejarse.
  2. Abre res/drawable/ic_gdg.xml.
  3. En la primera línea de código XML, busca y borra android:autoMirrored="true" para inhabilitar la duplicación.
  4. Consulta la vista previa o vuelve a ejecutar la app y abre la pantalla de GDG de búsqueda. El diseño ya debería estar fijo.

Paso 3: Deja que Android Studio haga el trabajo por ti

En el ejercicio anterior, diste tus primeros pasos para admitir idiomas con escritura de derecha a izquierda. Afortunadamente, Android Studio puede analizar tu app y configurar muchos aspectos básicos por ti.

  1. En list_item.xml, en TextView, vuelve a cambiar layout_marginStart a layout_marginLeft para que el escáner tenga algo que encontrar.
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
  1. En Android Studio, elige Refactor > Add RTL support where possible y marca las casillas para actualizar el manifiesto y los archivos de diseño para usar las propiedades de inicio y finalización.

  1. En el panel Refactoring Preview, busca la carpeta app y expándela hasta que se muestren todos los detalles.
  2. En la carpeta de la app, observa que el elemento layout_marginLeft que acabas de cambiar aparece como código para refactorizar.

  1. Ten en cuenta que la vista previa también muestra los archivos del sistema y de la biblioteca. Haz clic con el botón derecho en layout y layout-watch-v20, y en cualquier otra carpeta que no forme parte de app, y elige Exclude en el menú contextual.

  1. Continúa y refactoriza ahora. (Si aparece una ventana emergente sobre los archivos del sistema, asegúrate de haber excluido todas las carpetas que no forman parte del código de tu app).
  1. Ten en cuenta que layout_marginLeft volvió a ser layout_marginStart.

Paso 3: Explora las carpetas de configuraciones regionales

Hasta ahora, solo cambiaste la dirección del idioma predeterminado que se usa para la app. En el caso de una app de producción, enviarías el archivo strings.xml a un traductor para que lo traduzca a un idioma nuevo. Para este codelab, la app proporciona un archivo strings.xml en español (usamos Google Traductor para generar las traducciones, por lo que no son perfectas).

  1. En Android Studio, cambia la vista del proyecto a Project Files.
  2. Expande la carpeta res y observa las carpetas res/values y res/values-es. La "es" en el nombre de la carpeta es el código de idioma para español. Las carpetas values-"código de idioma" contienen valores para cada idioma admitido. La carpeta values sin extensión contiene los recursos predeterminados que se aplican de otro modo.

  1. En values-es, abre strings.xml y observa que todas las cadenas están en español.
  2. En Android Studio, abre activity_main.xml en la pestaña Design.
  3. En el menú desplegable Configuración regional para la vista previa, elige Español. Ahora, el texto debería estar en español.

  1. [Opcional] Si dominas un idioma de derecha a izquierda, crea una carpeta values y un archivo strings.xml en ese idioma, y prueba cómo se ve en tu dispositivo.
  2. [Opcional] Cambia la configuración de idioma en tu dispositivo y ejecuta la app. Asegúrate de no cambiar el idioma del dispositivo a uno que no entiendas, ya que será un poco difícil deshacer el cambio.

En la tarea anterior, modificaste tu app de forma manual y, luego, usaste Android Studio para verificar si había más mejoras de RTL que realizar.

La app de Prueba de accesibilidad es tu mejor aliada cuando se trata de hacer que tu app sea accesible. Analiza tu app en el dispositivo de destino y sugiere mejoras, como agrandar los objetivos táctiles, aumentar el contraste y proporcionar descripciones para las imágenes, para que tu app sea más accesible. La Prueba de accesibilidad es un producto de Google que puedes instalar desde Play Store.

Paso 1: Instala y ejecuta Prueba de accesibilidad

  1. Abre Play Store y accede si es necesario. Puedes hacerlo en tu dispositivo físico o en el emulador. En este codelab, se usa el emulador.
  1. En Play Store, busca Prueba de accesibilidad de Google LLC. Asegúrate de obtener la app correcta, emitida por Google, ya que cualquier análisis requiere muchos permisos.

  1. Instala el escáner en el emulador.
  2. Una vez instalado, haz clic en Abrir.
  3. Haz clic en Comenzar.
  4. Haz clic en Aceptar para iniciar la configuración de Prueba de accesibilidad en Configuración.

  1. Haz clic en Prueba de accesibilidad para ir a la configuración de Accesibilidad del dispositivo.

  1. Haz clic en Usar servicio para habilitarlo.

  1. Sigue las instrucciones en pantalla y otorga todos los permisos.
  2. Luego, haz clic en Aceptar y vuelve a la pantalla principal. Es posible que veas un botón azul con una marca de verificación en algún lugar de la pantalla. Si haces clic en este botón, se activará la prueba de la app en primer plano. Para cambiar la posición del botón, arrástralo. Este botón permanece en la parte superior de cualquier app, por lo que puedes activar las pruebas en cualquier momento.

  1. Abre o ejecuta tu app.
  2. Haz clic en el botón azul y acepta las advertencias y los permisos de seguridad adicionales.

La primera vez que haces clic en el ícono de Accessibility Scanner, la app te pide permiso para acceder a todo lo que se muestra en la pantalla. Este permiso parece muy peligroso, y lo es.

Casi nunca deberías otorgar un permiso como este, ya que permite que las apps lean tu correo electrónico o incluso obtengan la información de tu cuenta bancaria. Sin embargo, para que la Prueba de accesibilidad funcione, debe examinar tu app de la misma manera en que lo haría un usuario, por lo que necesita este permiso.

  1. Haz clic en el botón azul y espera a que se complete el análisis. Verás algo como la siguiente captura de pantalla, con el título y el FAB encerrados en un recuadro rojo. Esto indica dos sugerencias para mejorar la accesibilidad en esta pantalla.

  1. Haz clic en el cuadro que rodea a GDG Finder. Se abrirá un panel con información adicional, como se muestra a continuación, que indica problemas con el contraste de la imagen.
  2. Expande la información de Contraste de imagen y la herramienta sugerirá soluciones.
  3. Haz clic en las flechas a la derecha para obtener información sobre el siguiente elemento.

  1. En tu app, navega a la pantalla Apply for GDG y escanéala con la app de Prueba de accesibilidad. Esto te dará varias sugerencias, como se muestra a continuación a la izquierda. 12, para ser exactos. Para ser justos, algunos de esos duplicados son de artículos similares.
  2. Haz clic en el ícono de “pila” en la barra de herramientas inferior para obtener una lista de todas las sugerencias, como se muestra a continuación en la captura de pantalla de la derecha. Abordarás todos estos problemas en este codelab.

El Suite de Accesibilidad Android, una colección de apps de Google, incluye herramientas para ayudar a que las apps sean más accesibles. Incluye herramientas como TalkBack. TalkBack es un lector de pantalla que ofrece comentarios auditivos, hápticos y por voz, lo que permite a los usuarios navegar y consumir contenido en sus dispositivos sin usar los ojos.

Resulta que TalkBack no solo lo usan las personas ciegas, sino también muchas personas que tienen algún tipo de discapacidad visual. O incluso personas que solo quieren descansar la vista.

Por lo tanto, la accesibilidad es para todos. En esta tarea, probarás TalkBack y actualizarás tu app para que funcione bien con él.

Paso 1: Instala y ejecuta Accessibility Suite

TalkBack viene preinstalado en muchos dispositivos físicos, pero en un emulador, debes instalarlo.

  1. Abre la app de Play Store.
  2. Busca el Suite de Accesibilidad. Asegúrate de que sea la app correcta de Google.
  3. Si no está instalada, instala la Suite de Accesibilidad.
  4. Para habilitar TalkBack en el dispositivo, ve a Configuración > Accesibilidad y selecciona Usar servicio para activar TalkBack. Al igual que el escáner de accesibilidad, TalkBack requiere permisos para leer el contenido de la pantalla. Una vez que aceptes las solicitudes de permiso, TalkBack te dará la bienvenida con una lista de instructivos para enseñarte a usar TalkBack de manera eficaz.
  5. Haz una pausa aquí y realiza los instructivos, aunque solo sea para aprender a desactivar TalkBack cuando termines.
  6. Para salir del tutorial, haz clic en el botón Atrás para seleccionarlo y, luego, presiona dos veces en cualquier lugar de la pantalla.
  1. Explora la app de GDG Finder con TalkBack. Observa los lugares en los que TalkBack no te brinda información útil sobre la pantalla o un control. Corregirás esto en el siguiente ejercicio.

Paso 2: Agrega una descripción del contenido

Los descriptores de contenido son etiquetas descriptivas que explican el significado de las vistas. La mayoría de tus vistas deben tener descripciones de contenido.

  1. Con la app de GDG Finder en ejecución y TalkBack habilitado, navega a la pantalla Apply to run GDG.
  2. Presiona la imagen principal… y no sucede nada.
  3. Abre add_gdg_fragment.xml.
  4. En el ImageView, agrega un atributo de descriptor de contenido como se muestra a continuación. La cadena stage_image_description se proporciona en strings.xml.
android:contentDescription="@string/stage_image_description"
  1. Ejecuta tu app.
  2. Navega a Apply to run GDG y haz clic en la imagen. Ahora deberías escuchar una breve descripción de la imagen.
  3. [Opcional] Agrega descripciones de contenido para las demás imágenes de esta app. En una app de producción, todas las imágenes deben tener descripciones de contenido.

Paso 3: Agrega sugerencias a los campos de texto editables

En el caso de los elementos editables, como un EditText, puedes usar android:hint en el XML para ayudar a los usuarios a saber qué escribir. Una sugerencia siempre se muestra en la IU, ya que es el texto predeterminado en un campo de entrada.

  1. Aún en add_gdg_fragment.xml
  2. Agrega descripciones y sugerencias de contenido. Usa el siguiente código como guía.

Agregar a textViewIntro:

android:contentDescription="@string/add_gdg"

Agrega lo siguiente a los textos de edición, respectivamente:

android:hint="@string/your_name_label"

android:hint="@string/email_label"

android:hint="@string/city_label"

android:hint="@string/country_label"

android:hint="@string/region_label"
  1. Agrega una descripción del contenido a labelTextWhy.
android:contentDescription="@string/motivation" 
  1. Agrega una sugerencia a EditTextWhy. Una vez que hayas etiquetado los cuadros de edición, agrega una descripción del contenido a la etiqueta y también una sugerencia al cuadro.
android:hint="@string/enter_motivation"
  1. Agrega una descripción del contenido para el botón de envío. Todos los botones deben tener una descripción de lo que sucede si se presionan.
android:contentDescription="@string/submit_button_description"
  1. Ejecuta tu app con TalkBack habilitado y completa el formulario para solicitar la ejecución de un GDG.

Paso 4: Crea un grupo de contenido

Para los controles de IU que TalkBack debe tratar como un grupo, puedes usar la agrupación de contenido. El contenido relacionado que se agrupa se anuncia en conjunto. De esta manera, los usuarios de tecnología de asistencia no necesitarán deslizar el dedo, explorar ni esperar con tanta frecuencia para descubrir toda la información en la pantalla. Esto no afecta la forma en que aparecen los controles en la pantalla.

Para agrupar componentes de la IU, envuélvelos en un ViewGroup, como un LinearLayout. En la app de GDG Finder, los elementos labelTextWhy y editTextWhy son excelentes candidatos para agruparse, ya que pertenecen juntos semánticamente.

  1. Abre add_gdg_fragment.xml.
  2. Encapsula un LinearLayout alrededor de LabelTextWhy y EditTextWhy para crear un grupo de contenido. Copia y pega el siguiente código. Este LinearLayout ya contiene algunos de los estilos que necesitas. (Asegúrate de que el button esté FUERA del LinearLayout).
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
            android:layout_height="wrap_content" android:focusable="true"
            app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
            android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
            app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
            android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
            android:layout_marginBottom="8dp">

     <!-- label and edit text here –>

<LinearLayout/>
  1. Selecciona Code > Reformat code para aplicar la sangría correcta a todo el código.
  2. Quita todos los márgenes de diseño de labelTextWhy y editTextWhy.
  3. En labelTextWhy, cambia la restricción layout_constraintTop_toTopOf a contentGroup.
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
  1. En editTextWhy, cambia la restricción layout_constraintBottom_toBottomOf a contentGroup.
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
  1. Restringe EditTextRegion y Button a contentGroup para deshacerte de los errores.
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
  1. Agrega márgenes al LinearLayout. De manera opcional, extrae este margen como una dimensión.
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"

Si necesitas ayuda, compara tu código con el add_gdg_fragment.xml en el código de solución.

  1. Ejecuta tu app y explora la pantalla Apply to run GDG con TalkBack.

Paso 5: Agrega una región live

Actualmente, la etiqueta del botón de envío es Aceptar. Sería mejor que el botón tuviera una etiqueta y una descripción antes de que se envíe el formulario, y que cambiara de forma dinámica a una etiqueta y una descripción de contenido diferentes después de que el usuario haga clic y se envíe el formulario. Puedes hacerlo con una región activa.

Una región live indica a los servicios de accesibilidad si se debe notificar al usuario cuando cambia una vista. Por ejemplo, informar al usuario sobre una contraseña incorrecta o un error de red es una excelente manera de hacer que tu app sea más accesible. En este ejemplo, para que sea sencillo, le informas al usuario cuando el botón de envío cambia de estado.

  1. Abre add_gdg_fragment.xml.
  2. Cambia la asignación de texto del botón a Enviar con el recurso de cadena submit proporcionado.
android:text="@string/submit"
  1. Agrega una región activa al botón configurando el atributo android:accessibilityLiveRegion. A medida que escribes, tienes varias opciones para su valor. Según la importancia del cambio, puedes elegir si interrumpir al usuario. Con el valor "assertive", los servicios de accesibilidad interrumpen el discurso en curso para anunciar de inmediato los cambios en esta vista. Si configuras el valor como "none", no se anunciarán los cambios. Si se configura como "cortés", los servicios de accesibilidad anuncian los cambios, pero esperan su turno. Establece el valor en "polite".

android:accessibilityLiveRegion="polite"
  1. En el paquete add, abre AddGdgFragment.kt.
  2. Dentro de showSnackBarEvent Observer, después de que termines de mostrar SnackBar, establece una nueva descripción del contenido y texto para el botón.
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
  1. Ejecuta la app y haz clic en el botón. Lamentablemente, el botón y la fuente son demasiado pequeños.

Paso 6: Corrige el diseño del botón

  1. En add_gdg_fragment.xml, cambia los atributos width y height del botón a wrap_content para que se vea la etiqueta completa y el botón tenga un buen tamaño.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
  1. Borra los atributos backgroundTint, textColor y textSize del botón para que la app use el mejor diseño de tema.
  2. Borra el atributo textColor de textViewIntro. Los colores del tema deben proporcionar un buen contraste.
  3. Ejecuta la app. Observa el botón Submit, que es mucho más útil. Haz clic en Enviar y observa cómo cambia a Listo.

Los chips son elementos compactos que representan un atributo, texto, entidad o acción. Permiten que los usuarios ingresen información, seleccionen una opción, filtren contenido o activen una acción.

El widget Chip es un wrapper de vista delgado alrededor de ChipDrawable, que contiene toda la lógica de diseño y dibujo. La lógica adicional existe para admitir la navegación táctil, con mouse, teclado y de accesibilidad. El chip principal y el ícono de cerrar se consideran subvistas lógicas independientes y contienen su propio comportamiento y estado de navegación.

Los chips usan elementos de diseño dibujables. Los elementos de diseño de Android te permiten dibujar imágenes, formas y animaciones en la pantalla, y pueden tener un tamaño fijo o dinámico. Puedes usar imágenes como elementos de diseño, como las imágenes de la app del GDG, y puedes usar dibujos vectoriales para dibujar todo lo que se te ocurra. También hay un elemento de diseño redimensionable llamado elemento de diseño de 9 parches, que no se aborda en este codelab. El logotipo del GDG, en drawable/ic_gdg.xml, es otro elemento de diseño.

Los elementos de diseño no son vistas, por lo que no puedes colocar un elemento de diseño directamente dentro de un ConstraintLayout. Debes colocarlo dentro de un ImageView. También puedes usar elementos de diseño para proporcionar un fondo para una vista de texto o un botón, y el fondo se dibuja detrás del texto.

Paso 1: Agrega chips a la lista de GDG

El chip marcado a continuación usa tres elementos de diseño. El fondo y la marca de verificación son elementos de diseño. Cuando tocas el chip, se crea un efecto en cadena, que se realiza con un RippleDrawable especial que muestra un efecto en cadena en respuesta a los cambios de estado.

En esta tarea, agregarás chips a la lista de GDG y harás que cambien de estado cuando se seleccionen. En este ejercicio, agregarás una fila de botones llamados chips en la parte superior de la pantalla Search. Cada botón filtra la lista de GDG para que el usuario solo reciba resultados de la región seleccionada. Cuando se selecciona un botón, este cambia su fondo y muestra una marca de verificación.

  1. Abre fragment_gdg_list.xml.
  2. Crea un com.google.android.material.chip.ChipGroup dentro del HorizontalScrollView.. Establece su propiedad singleLine en true para que todas las chips se alineen en una línea horizontal en la que el usuario pueda desplazarse. Establece la propiedad singleSelection en true para que solo se pueda seleccionar un chip del grupo a la vez. Este es el código.
<com.google.android.material.chip.ChipGroup
    android:id="@+id/region_list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:singleSelection="true"
    android:padding="@dimen/spacing_normal"/>
  1. En la carpeta layout, crea un nuevo archivo de recursos de diseño llamado region.xml para definir el diseño de un Chip.
  2. En region.xml, reemplaza todo el código por el diseño de un Chip como se indica a continuación. Ten en cuenta que este Chip es un componente de Material. También ten en cuenta que obtienes la marca de verificación configurando la propiedad app:checkedIconVisible. Recibirás un error por la falta del color selected_highlight.
<?xml version="1.0" encoding="utf-8"?>

<com.google.android.material.chip.Chip
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Widget.MaterialComponents.Chip.Choice"
        app:chipBackgroundColor="@color/selected_highlight"
        app:checkedIconVisible="true"
        tools:checked="true"/>
  1. Para crear el color selected_highlight faltante, coloca el cursor en selected_highlight, abre el menú de intención y crea un recurso de color para el elemento destacado seleccionado. Las opciones predeterminadas son adecuadas, así que haz clic en Aceptar. El archivo se crea en la carpeta res/color.
  2. Abre res/color/selected_highlight.xml. En esta lista de estados de color, codificada como un <selector>, puedes proporcionar diferentes colores para diferentes estados. Cada estado y el color asociado se codifican como un <item>. Consulta Temas de color para obtener más información sobre estos colores.
  1. Dentro de <selector>, agrega un elemento con un color predeterminado colorOnSurface a la lista de estados. En las listas de estados, es importante abarcar siempre todos los estados. Una forma de hacerlo es tener un color predeterminado.
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
  1. Sobre el color predeterminado, agrega un item con un color de colorPrimaryVariant y restringe su uso a cuando el estado seleccionado sea true. Las listas de estados se procesan de arriba abajo, como una instrucción case. Si no coincide ninguno de los estados, se aplica el estado predeterminado.
<item android:color="?attr/colorPrimaryVariant"
         android:state_selected="true" />

Paso 2: Muestra la fila de chips

La app de GDG crea una lista de chips que muestran las regiones que tienen GDG. Cuando se selecciona un chip, la app filtra los resultados para mostrar solo los del GDG de esa región.

  1. En el paquete search, abre GdgListFragment.kt.
  2. En onCreateView(), justo encima de la instrucción return, agrega un observador en viewModel.regionList y anula onChanged(). Cuando cambia la lista de regiones que proporciona el modelo de vista, se deben volver a crear los chips. Agrega una sentencia para que se muestre un resultado de inmediato si el data proporcionado es null.
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
        override fun onChanged(data: List<String>?) {
             data ?: return
        }
})
  1. Dentro de onChanged(), debajo de la prueba de nulos, asigna binding.regionList a una nueva variable llamada chipGroup para almacenar en caché el regionList.
val chipGroup = binding.regionList
  1. A continuación, crea un nuevo layoutInflator para inflar chips desde chipGroup.context.
val inflator = LayoutInflater.from(chipGroup.context)
  1. Limpia y vuelve a compilar tu proyecto para deshacerte del error de vinculación de datos.

Debajo del inflador, ahora puedes crear los chips reales, uno para cada región en regionList.

  1. Crea una variable, children, para contener todos los chips. Asigna una función de asignación al data pasado para crear y devolver cada chip.
val children = data.map {} 
  1. Dentro de la expresión lambda del mapa, para cada regionName, crea e infla un chip. A continuación, se incluye el código completo.
val children = data.map {
   val children = data.map { regionName ->
       val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
       chip.text = regionName
       chip.tag = regionName
       // TODO: Click listener goes here.
       chip
   }
}
  1. Dentro de la lambda, justo antes de devolver el chip, agrega un objeto de escucha de clics. Cuando se haga clic en chip, establece su estado en checked. Llama a onFilterChanged() en el viewModel, lo que activa una secuencia de eventos que recupera el resultado de este filtro.
chip.setOnCheckedChangeListener { button, isChecked ->
   viewModel.onFilterChanged(button.tag as String, isChecked)
}
  1. Al final de la lambda, quita todas las vistas actuales de chipGroup y, luego, agrega todos los chips de children a chipGroup. (No puedes actualizar los chips, por lo que debes quitar y volver a crear el contenido de chipGroup).
chipGroup.removeAllViews()

for (chip in children) {
   chipGroup.addView(chip)
}

El observador completado debería verse de la siguiente manera:

   override fun onChanged(data: List<String>?) {
       data ?: return

       val chipGroup = binding.regionList
       val inflator = LayoutInflater.from(chipGroup.context)

       val children = data.map { regionName ->
           val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
           chip.text = regionName
           chip.tag = regionName
           chip.setOnCheckedChangeListener { button, isChecked ->
               viewModel.onFilterChanged(button.tag as String, isChecked)
           }
           chip
       }
       chipGroup.removeAllViews()

       for (chip in children) {
           chipGroup.addView(chip)
       }
   }
})
  1. Ejecuta tu app y busca GDG para abrir la pantalla Search y usar los nuevos chips. A medida que hagas clic en cada chip, la app mostrará los grupos de filtros debajo de él.

El modo nocturno permite que tu app cambie sus colores a un tema oscuro, por ejemplo, cuando la configuración del dispositivo se establece para habilitar el modo nocturno. En el modo nocturno, las apps cambian sus fondos claros predeterminados por fondos oscuros y modifican todos los demás elementos de la pantalla según corresponda.

Paso 1: Habilita el modo nocturno

Para proporcionar el tema oscuro para tu app, cambia su tema del tema Light a un tema llamado DayNight. El tema DayNight aparece claro u oscuro, según el modo.

  1. En styles.xml,, cambia el tema principal AppTheme de Light a DayNight.
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
  1. En el método onCreate() de MainActivity, llama a AppCompatDelegate.setDefaultNightMode() para activar el tema oscuro de forma programática.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
  1. Ejecuta la app y verifica que haya cambiado al tema oscuro.

Paso 2: Genera tu propia paleta de colores del tema oscuro

Para personalizar el tema oscuro, crea carpetas con el calificador -night para que se use el tema oscuro. Por ejemplo, puedes tener colores específicos en el modo oscuro creando una carpeta llamada values-night.

  1. Visita la herramienta de selector de color de material.io y crea una paleta de colores para el tema nocturno. Por ejemplo, puedes basarlo en un color azul oscuro.
  2. Genera y descarga el archivo colors.xml.
  3. Cambia a la vista Project Files para enumerar todas las carpetas de tu proyecto.
  4. Busca la carpeta res y expándela.
  5. Crea una carpeta de recursos res/values-night.
  6. Agrega el nuevo archivo colors.xml a la carpeta de recursos res/values-night.
  7. Ejecuta tu app, aún con el modo nocturno habilitado, y la app debería usar los colores nuevos que definiste para res/values-night. Observa que los chips usan el nuevo color secundario.

Proyecto de Android Studio: GDGFinderFinal

Compatibilidad con idiomas RTL

  • En el manifiesto de Android, establece android:supportsRtl="true".
  • Puedes obtener una vista previa de RTL en el emulador y usar tu propio idioma para verificar los diseños de pantalla. En un dispositivo o emulador, abre Configuración y, en Opciones para desarrolladores, selecciona Forzar diseño de RTL.
  • Reemplaza las referencias a Left y Right por referencias a Start y End.
  • Borra android:autoMirrored="true" para inhabilitar la duplicación de elementos de diseño.
  • Elige Refactor > Add RTL support where possible para que Android Studio haga el trabajo por ti.
  • Usa carpetas values-"código de idioma" para almacenar recursos específicos del idioma.

Cómo realizar análisis de accesibilidad

Diseña para TalkBack con descripciones de contenido

  • Instala el Kit de Accesibilidad Android de Google, que incluye TalkBack.
  • Agrega descripciones de contenido a todos los elementos de la IU. Por ejemplo:
    android:contentDescription="@string/stage_image_description"
  • En el caso de un elemento editable, como un EditText, usa un atributo android:hint en el XML para proporcionar una sugerencia al usuario sobre qué escribir.
  • Crea grupos de contenido agrupando elementos relacionados en un grupo de vistas.
  • Crea una región activa para brindarles a los usuarios comentarios adicionales con android:accessibilityLiveRegion.

Usa chips para implementar un filtro

  • Los chips son elementos compactos que representan un atributo, texto, entidad o acción.
  • Para crear un grupo de chips, usa un com.google.android.material.chip.ChipGroup.
  • Define el diseño para un com.google.android.material.chip.Chip.
  • Si quieres que los chips cambien de color, proporciona una lista de estados de color como un <selector> con colores con estado:
    <item android:color="?attr/colorPrimaryVariant"
    android:state_selected="true" />
  • Vincula los chips a datos activos agregando un observador a los datos en el ViewModel.
  • Para mostrar los chips, crea un inflador para el grupo de chips:
    LayoutInflater.from(chipGroup.context)
  • Crea los chips, agrega un objeto de escucha de clics que active la acción deseada y agrega los chips al grupo de chips.

Admite el modo oscuro

  • Usa DayNight AppTheme para admitir el modo oscuro.
  • Puedes configurar el modo oscuro de forma programática:
    AppCompatDelegate.setDefaultNightMode()
  • Crea una carpeta de recursos res/values-night para proporcionar colores y valores personalizados para el modo oscuro.

Documentación para desarrolladores de Android:

Otros recursos:

En esta sección, se enumeran las posibles actividades para el hogar para los alumnos que trabajan en este codelab como parte de un curso dirigido por un instructor. Depende del instructor hacer lo siguiente:

  • Si es necesario, asigna una tarea.
  • Comunicarles a los alumnos cómo enviar las actividades para el hogar.
  • Califica las actividades para el hogar.

Los instructores pueden usar estas sugerencias en la medida que quieran y deben asignar cualquier otra actividad para el hogar que consideren apropiada.

Si estás trabajando en este codelab por tu cuenta, usa estas actividades para el hogar para probar tus conocimientos.

Pregunta 1

¿Cuál de estas opciones es obligatoria para admitir idiomas con escritura de derecha a izquierda?

▢ Reemplaza Left y Right en las propiedades por Start y End.

▢ Cambiar a un idioma con escritura de derecha a izquierda

▢ Asegurarse de que todos los íconos usen android:autoMirrored="true"

▢ Proporciona descripciones de contenido

Pregunta 2

¿Cuáles de estas herramientas de accesibilidad vienen integradas en la mayoría de los dispositivos Android?

▢ TalkBack

▢ Prueba de accesibilidad

▢ En Android Studio, Refactor > Add RTL support where possible

▢ Lint

Pregunta 3

¿Cuál de las siguientes afirmaciones sobre los chips no es verdadera?

▢ Muestras chips como parte de un ChipGroup.

▢ Puedes proporcionar una lista de estados de color para un ChipGroup.

▢ Los chips son elementos compactos que representan una entrada, un atributo o una acción.

▢ Siempre debes habilitar DarkTheme si tu app usa chips.

Pregunta 4

¿Qué tema te brinda un diseño para los modos claro y oscuro?

DayNight

DarkTheme

DarkAndLightTheme

Light

Pregunta 5

¿Qué es una región live?

▢ Un nodo que contiene información importante para el usuario

▢ Una región de la pantalla que cambia de forma según los lineamientos de Material

▢ Una vista que permite la transmisión de video

▢ Un elemento de diseño animado