Cómo etiquetar imágenes y componentes visuales en Android con Content Description

En el desarrollo de aplicaciones para Android, la accesibilidad es un aspecto que no puede dejarse de lado. Uno de los errores más comunes en las interfaces de aplicaciones móviles es utilizar iconos o imágenes sin acompañarlos de una descripción accesible. Para los usuarios que dependen de TalkBack u otros lectores de pantalla, estos elementos pueden convertirse en barreras de accesibilidad muy severas si no cuentan con la información adecuada para identificar la funcionalidad de dichos botones o elementos visuales.

La propiedad contentDescription permite añadir una etiqueta textual a cualquier componente visual, de forma que TalkBack la anuncie en lugar de limitarse a leer un nombre técnico como “ic_send” o a ignorar la imagen por completo.

Ejemplo básico en XML

Un caso clásico es un botón con un icono de avión de papel que representa la acción de enviar un mensaje. Visualmente resulta evidente, pero sin descripción accesible no es comprensible para quien no puede ver la pantalla:

<ImageButton
android:id="@+id/sendButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_send"
android:contentDescription="Enviar mensaje"
/>

En este ejemplo, TalkBack leerá “Enviar mensaje” al situarse sobre el botón, en lugar de un nombre de archivo técnico.

Ejemplo con Jetpack Compose

En Compose, la accesibilidad se maneja mediante modificadores de semántica. El equivalente a contentDescription sería:

IconButton(
onClick = { /* Acción para enviar */ },
modifier = Modifier.semantics { contentDescription = "Enviar mensaje" }
) {
Icon(
imageVector = Icons.Default.Send,
contentDescription = null // Evitamos redundancia
)
}

En este ejemplo el botón anuncia la etiqueta “Enviar mensaje” al interactuar con TalkBack. El icono interno no necesita contentDescription porque ya se ha definido en el contenedor.

Buenas prácticas

La propiedad contentDescription es sencilla de usar, pero conviene aplicarla con criterio:

  1. Priorizar la función: un icono de engranaje para un botón para ir a los ajustes de la app no debería describirse como “rueda dentada”, sino como “Ajustes”, que es la acción real.
  2. Ser breve y claro: descripciones cortas facilitan la navegación. Un botón que abre un chat debe decir “Abrir chat”, no “Icono de burbuja de diálogo para iniciar conversación”.
  3. Evitar redundancias: si un TextView ya tiene texto visible, no es necesario repetirlo en contentDescription. TalkBack lo leerá automáticamente.
  4. Ocultar lo decorativo: para imágenes que solo son decorativas, se debe establecer android:contentDescription=»@null» en XML o contentDescription = null en Compose. De esta forma TalkBack las ignora.

Etiquetar adecuadamente los componentes visuales no solo es una buena práctica de desarrollo, sino un compromiso con la inclusión digital. Al igual que ocurre con cualquier aspecto del diseño, dedicar unos segundos a escribir una descripción accesible marca la diferencia entre una app usable y otra que excluye a parte de sus usuarios. La propiedad contentDescription es una de las herramientas más simples y a la vez más poderosas que Android pone en manos de los desarrolladores para mejorar la accesibilidad. Añadir una descripción clara y precisa a imágenes e iconos garantiza que los usuarios con lectores de pantalla comprendan e interactúen con la interfaz en igualdad de condiciones.

Cómo etiquetar imágenes y componentes visuales en iOS y MacOS con SwiftUI

El desarrollo de interfaces con SwiftUI ofrece muchas ventajas en simplicidad y expresividad, pero también implica una responsabilidad clara: garantizar que todos los componentes sean accesibles. En este sentido, el modificador accessibilityLabel juega un papel fundamental, ya que permite proporcionar descripciones comprensibles para los usuarios que navegan mediante VoiceOver u otros productos de apoyo.

En una aplicación móvil, es habitual encontrar botones representados solo con iconos, imágenes decorativas o gráficos complejos que transmiten información de manera visual. Si estos elementos no cuentan con una etiqueta accesible, el lector de pantalla se limitará a leer su nombre interno por ejemplo, “paperplane.fill” o incluso no los anunciará, lo que genera una experiencia frustrante y excluyente.

El modificador accessibilityLabel resuelve este problema al ofrecer un texto alternativo que describe la función o el significado del elemento. La idea es que, al interactuar con el componente, VoiceOver verbalice la etiqueta definida en lugar del nombre interno o el contenido gráfico.

Ejemplo básico

Un caso típico es un botón con un icono de avión de papel para enviar un mensaje. Visualmente resulta evidente, pero sin una etiqueta accesible el usuario ciego no comprendería su propósito:

Button(action: {
// Acción para enviar
}) {
Image(systemName: "paperplane.fill")
.font(.largeTitle)
}
.accessibilityLabel("Enviar mensaje")

Al añadir .accessibilityLabel(«Enviar mensaje»), VoiceOver anuncia esa frase, y la acción del botón se vuelve comprensible y usable para todas las personas.

Además, no sólo se benefician los usuarios ciegos, también el sistema de Voice control para iOS y MacOS utilizará ese texto para localizar el botón y poderlo pulsar de forma más cómoda para el usuario.

Más allá de los iconos

El uso de accessibilityLabel no se limita a los botones. También puede aplicarse a imágenes que transmiten información importante. Una fotografía, un logotipo o un gráfico que refuerce la identidad de una app debería llevar una etiqueta adecuada.

Image("company_logo")
.resizable()
.frame(width: 120, height: 120)
.accessibilityLabel("Logotipo de la empresa Ejemplo")

En este caso, el lector de pantalla transmitirá la descripción de la imagen en lugar de identificar un elemento inaccesible o verbalizar el nombre del fichero del logotipo de la empresa.

Buenas prácticas

La potencia de accessibilityLabel reside en su sencillez, pero eso no significa que se deba aplicarlo sin reflexión. Es importante tener en cuenta algunas recomendaciones:

  1. Claridad antes que detalle: las etiquetas deben ser breves y concretas. No conviene describir minuciosamente una imagen si con dos palabras es suficiente para transmitir la idea.
  2. Función antes que forma: en un botón, es más importante describir la acción que detallar el icono. Por ejemplo, “Abrir ajustes” comunica más que “Engranaje”.
  3. Evitar redundancias: si un elemento ya tiene un texto visible, añadir un accessibilityLabel idéntico puede resultar repetitivo. En esos casos, lo mejor es dejar que VoiceOver lea directamente el texto.
  4. No etiquetar lo decorativo: si una imagen es meramente estética y no aporta información, lo correcto es marcarla como ignorada con .accessibilityHidden(true).

Etiquetar imágenes y componentes visuales no es un añadido opcional, sino un paso esencial para construir apps accesibles, usables y respetuosas con la diversidad de las personas que las utilizan. El modificador accessibilityLabel es un elemento sencillo y que ayuda a solucionar barreras severas de accesibilidad con un mínimo esfuerzo. Con unas pocas líneas de código, es posible transformar una interfaz visual en una experiencia inclusiva, asegurando que todos los usuarios, independientemente de cómo interactúen con su dispositivo, comprendan y disfruten la aplicación.

La inteligencia artificial como aliada para los programadores ciegos

La inteligencia artificial está transformando la forma en que se desarrolla el software. Desde hace unos años, el auge de los modelos de lenguaje y de las herramientas de autocompletado inteligente ha abierto nuevas posibilidades que van mucho más allá de la simple ayuda para escribir código más rápido.

Para una persona ciega que se dedica a programar, estas tecnologías representan no solo un aumento de productividad, sino un refuerzo de autonomía y acceso a recursos que antes resultaban más costosos de alcanzar.

Uno de los ámbitos donde la IA muestra mayor potencial es en la asistencia al escribir código. Los asistentes de programación, integrados ya en entornos como Visual Studio Code, Xcode o Android Studio, permiten recibir sugerencias de código completas que se adaptan al contexto de lo que se está escribiendo. Esto reduce el tiempo invertido en consultar la documentación del lenguaje y la plataforma así como el esfuerzo extra en la memorización de esta información.

La Inteligencia artificial también está entrando en el terreno de la depuración de código. Existen herramientas capaces de analizar un bloque de código y proponer explicaciones de por qué falla una prueba, dónde puede estar el error lógico o qué cambios podrían mejorar su rendimiento. Para un programador ciego, este acompañamiento supone un ahorro de tiempo, pero también un refuerzo pedagógico. Además, en muchos casos, las herramientas de depuración habituales resultan inaccesibles para las personas ciegas por problemas de accesibilidad en estas herramientas de depuración. Poder obtener una idea o una explicación de por qué está fallando algo puede ayudar al proceso de depuración de bloques de código.

La documentación es otro frente donde la inteligencia artificial está marcando la diferencia. Generar comentarios, crear documentación técnica a partir de funciones o clases, traducir explicaciones a varios idiomas o resumir artículos largos son tareas que, integradas en el flujo de desarrollo, facilitan la comunicación con otros equipos y el mantenimiento de los proyectos.

Falta de accesibilidad en la Inteligencia artificial

Aunque la aparición de estas herramientas, aparentemente, impliquen beneficios para todos los programadores, en realidad estas herramientas presentan un problema común para mucho del software utilizado para trabajar. Este problema es la falta de accesibilidad. En muchos casos estas herramientas integradas en los entornos de desarrollo utilizan componentes visuales o un lenguaje visual que resulta inaccesible para lectores de pantalla o, en otros casos, no existe la posibilidad de controlar las funciones de estas herramientas de autocompletado de código desde el teclado. Esto hará que el catálogo de entornos de desarrollo disponible para las personas ciegas se reduzca ya que, en un futuro, no sólo se tendrá que observar si el editor de código o los botones del entorno de desarrollo son accesibles, también se deberá observar si la forma en que el asistente de autocompletado de código es accesible.

En muchos casos, poco a poco, gracias al feedback de los programadores ciegos que notifican a los responsables de estos entornos de desarrollo de los problemas de accesibilidad, las herramientas de autocompletado van siendo un poco más accesible cada día. El problema es el de siempre: pocos programadores ciegos reportan y ayudan a hacer más accesibles los entornos de desarrollo y las herramientas que los acompañan.

La solución está en la personalización

La capacidad de muchas herramientas de poder personalizar distintos aspectos visuales y comportamientos permiten superar, en muchos casos, la falta de accesibilidad de estas herramientas. Poder asignar un atajo de teclado a una función de la herramienta de autocompletado o personalizar los colores de la pantalla de visualización para que las funciones de OCR del lector de pantallas puedan identificar cual es la zona del editor y cual es la zona de la recomendación facilita la identificación de estos elementos.

En cualquier caso estos son parches para la falta de una accesibilidad plena y completa en estas herramientas. Los programadores ciegos debemos seguir aportando feedback y reclamando accesibilidad para estos elementos del desarrollo de software.

El futuro para la programación

No debemos olvidar que la IA no sustituye la necesidad de criterio propio. La dependencia excesiva de las sugerencias puede llevar a errores invisibles, y la accesibilidad de estas herramientas aún tiene un largo camino por recorrer. Las interfaces gráficas, los atajos de teclado mal diseñados o la falta de descripciones adecuadas en los resultados pueden generar barreras nuevas. Por eso, la adopción de la IA debe ir acompañada de una mirada crítica y de una exigencia a los proveedores de que sus soluciones sean inclusivas desde el diseño.

Además, muchas de las soluciones propuestas para el código no incluyen atributos o elementos de accesibilidad. Sería muy irónico que un programador ciego desarrollase interfaces de usuario con problemas de accesibilidad por limitar su trabajo a copiar el código propuesto por una Inteligencia artificial sin prestar ni revisar el código propuesto por la herramienta.

Programación táctil para personas ciegas con Code Jumper

Code Jumper es un juguete físico que facilita el aprendizaje de los conceptos de la programación a personas ciegas.
Este proyecto ha sido desarrollado por Microsoft en colaboración con American Printing House for the Blind (APH).
Consiste en un sistema físico de piezas llamadas micro‑pods conectadas entre ellas mediante cables para definir un flujo de programa. Cada micro pod representa una operación o función de programación(Play, Loop, Selection, etc)
Una vez se hayan completado las conexiones entre piezas y cables para construir un programa, luego se puede reproducir mediante sonidos y narraciones auditivas accesibles. En el app, cada conexión genera una línea de código accesible mediante lectores de pantalla o el botón “leer código” en una consola que acompaña a esta herramienta.

¿Qué son los micro pods?

Un micro‑pod es una pieza física del tamaño aproximado de una pastilla de jabón, diseñada para ser manipulada fácilmente con las manos. Cada Micro pod tiene asociada una función de las posibles para construir un programa.

El micro pod tiene una forma ovalada o circular, con un aspecto aplanado. Fabricado en plástico rígido y con texturas que permiten diferenciarlos. Cada pod tiene conexiones y botones físicos que permiten identificarlo fácilmente. Las conexiones son similares a las clavijas de auriculares y los botones pueden ser selectores de apagado y encendido o diales para seleccionar un valor.

Contenidos y recursos educativos

APH ofrece un currículo de 19 lecciones de unas 25 horas con actividades guiadas, ejercicios, retos y videos.
Los tipos de piezas incluyen:

  • Secuencia y reproducir sonidos (Play pods)
  • Bucles y repeticiones (Loop pods), por ejemplo, tocar una canción infantil  
  • Variables y contadores (Constant, Variable plugs), p. ej. una cuenta atrás
  • Selección / condicionales y azar (Selection, Random plugs), p. ej. historias con desenlaces variables .
  • Bucles anidados, para construir patrones musicales complejos.

Además hay ejercicios más complejos llamados Code Jumper Puzzles donde se requieren soluciones más imaginativas.

Puedes adquirir Code jumper en su página oficial.

Code File Catcher: una herramienta para dar contexto a tus consultas a la IA

Muchas veces, cuando queremos pedir ayuda a una IA para depurar un fallo, revisar una estructura o mejorar un código, necesitamos enviar más que una simple función. Necesitamos compartir el contexto completo del proyecto: otros archivos, dependencias, configuraciones, etc.

Los entornos de desarrollo incluyen un navegador de archivos para moverte entre los distintos ficheros de un proyecto pero, en la mayoría de los casos, el navegador de archivos incluye alguna barrera de dificultad o la cantidad de ficheros es bastante grande lo que dificulta la tarea a los desarrolladores con discapacidad o con poca destreza a la hora de moverse en su entorno de desarrollo. Con Code File Catcher puedes hacer eso fácilmente.

Code File Catcher es una aplicación sencilla pero poderosa que te permite seleccionar una carpeta de tu disco, elegir los tipos de archivos de código que quieres incluir, y obtener automáticamente un texto con todo el contenido de esos archivos perfectamente organizado y listo para copiar o exportar.

Esto resulta especialmente útil si estás trabajando con asistentes de inteligencia artificial como ChatGPT, Gemini o similares, que requieren el contexto completo del código para ofrecer respuestas precisas y útiles.

Entre las distintas operaciones que puede realizar actualmente están: recopila todos los archivos fuente relevantes de un proyecto o carpeta, muestra un texto estructurado con el nombre del archivo y su contenido y puede copiar ese texto al portapapeles o exportarlo como archivo `.txt`.

El proyecto está disponible bajo una licencia libre en GitHub. Puedes consultarlo, usarlo, modificarlo y, si lo deseas, contribuir con mejoras o sugerencias. El proyecto está abierto a colaboraciones, especialmente si pueden ayudar a que la herramienta sea aún más útil para más personas.

Puedes encontrar el código del proyecto y participar en él en el repositorio de Code File Catcher en Github.

Obtener el idioma del sistema en AppleScript

En algunos proyectos con AppleScript puede que queramos dar soporte a varios idiomas. La solución inicial pasa por distribuir nuestro fichero de AppleScript adaptado a cada uno de los idiomas que queramos incluir en el proyecto. Esta solución es poco eficiente e incrementa mucho el coste de mantenimiento.

Pero si nuestro AppleScript pudiese detectar qué idioma necesita el usuario y se pudiera adaptar la selección de cadenas de texto al idioma que necesitemos podríamos utilizar un único fichero de AppleScript para todos los idioma.

Limitaciones y soluciones para identificar el idioma

En principio AppleScript no puede acceder a la información del sistema desde su propia librería de comandos. Pero sí podemos usar otros entornos para acceder a dicha información.

Por ejemplo, con el comando defaults tenemos acceso a mucha de la información del sistema. Si ejecutamos en la Terminal de MacOS el comando defaults read NSGlobalDomain AppleLanguages por la pantalla de la Terminal aparecerá algo como:

(
"es-ES",
"en-ES"
)

Es un array o lista de los idiomas y regiones que tenemos instalado en nuestro sistema. Como buscamos obtener un resultado con el texto es que representa a Español debemos cortar todo el texto sobrante para quedarnos con ese primer elemento de la lista.

Con el comando sed podemos realizar todas estas operaciones. Enlazando el comando defaults con sed podemos obtener lo que buscamos utilizando el comando:

defaults read NSGlobalDomain AppleLanguages | sed -n '2s/[^a-zA-Z-]//gp' | cut -d '-' -f1 

Al ejecutarlo en la Terminal aparecerá:

es

Ahora podemos utilizar un comando de Terminal en un AppleScript.

Función para AppleScript

Nuestra función finalmente quedaría así:

on getSystemLanguage()
    return do shell script "defaults read NSGlobalDomain AppleLanguages | sed -n '2s/[^a-zA-Z-]//gp' | cut -d '-' -f1"
end getSystemLanguage