Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Principios para mejorar la accesibilidad de las apps

Algunos usuarios de dispositivos Android tienen necesidades de accesibilidad diferentes de otros. Para ayudar a un grupo determinado de la población que comparte una necesidad de accesibilidad, el framework de Android brinda a los desarrolladores la capacidad de crear un servicio de accesibilidad, que les presenta el contenido de las apps y las opera en su nombre.

Android proporciona varios servicios de accesibilidad del sistema, incluidos los siguientes:

  • TalkBack: Ayuda a las personas con visión reducida o ciegas. Anuncia el contenido a través de una voz sintetizada y realiza acciones en una app en respuesta a los gestos del usuario.
  • Accesibilidad mejorada: Ayuda a las personas con discapacidades motoras. Destaca elementos interactivos y realiza acciones como respuesta cuando el usuario presiona un botón. Permite controlar el dispositivo con solo 1 o 2 botones.

Para ayudar a las personas con necesidades de accesibilidad a usar tu app como corresponde, esta debe seguir las prácticas recomendadas que se describen en esta página, que se basan en los lineamientos clave incluidos en Cómo mejorar la accesibilidad de las apps.

Cada una de las siguientes prácticas recomendadas puede mejorar la accesibilidad de tu app:

Etiqueta los elementos
Los usuarios deben poder comprender el contenido y el propósito de cada elemento de la IU interactivo y significativo en tu app.
Usa o extiende widgets del sistema
Compila a partir de los elementos de vista que incluye el framework, en lugar de crear tus propias vistas personalizadas. Las clases de vista y widget del framework ya proporcionan la mayoría de las capacidades de accesibilidad que necesita tu app.
Utiliza señales que no hagan uso del color
Los usuarios deben poder distinguir claramente entre categorías de elementos en una IU. Para ello, usa patrones y la posición, además del color, para expresar estas diferencias.
Mejora la accesibilidad del contenido multimedia
Agrega descripciones al contenido de video o audio de tu app a fin de que los usuarios que lo consuman no tengan que depender por completo de señales visuales o sonoras.

Etiqueta elementos

Es importante brindarles a los usuarios etiquetas útiles y descriptivas para cada elemento de la IU interactivo de tu app. En cada etiqueta, se debe explicar el significado y el propósito de un elemento específico. Los lectores de pantalla como TalkBack pueden leerles las etiquetas a los usuarios que dependen de estos servicios.

En la mayoría de los casos, debes especificar la descripción de un elemento de la IU determinado en el archivo de recursos de diseño que lo contiene. Aunque, por lo general, debes agregar etiquetas con el atributo contentDescription, como se explica en la guía sobre cómo mejorar la accesibilidad de las apps, hay otras técnicas de etiquetado que debes tener en cuenta, como se describe en las siguientes secciones.

Elementos editables

Cuando etiquetas elementos editables, como objetos EditText, resulta útil mostrar texto que brinde ejemplos de entradas válidas en el elemento, además de hacer que este texto de ejemplo esté disponible para los lectores de pantalla. En estos casos, puedes usar el atributo android:hint, como se muestra en el siguiente fragmento:

<!-- The hint text for en-US locale would be
     "Apartment, suite, or building". -->
<EditText
   android:id="@+id/addressLine2"
   android:hint="@string/aptSuiteBuilding" ... />

En este caso, el objeto View debe tener su atributo android:labelFor establecido en el ID del elemento EditText. Si deseas obtener más información, consulta la sección en la que se explica cómo etiquetar pares de elementos en los que uno describe al otro.

Pares de elementos en los que uno describe al otro

Es común que un elemento EditText determinado tenga un objeto View correspondiente que describa el contenido que los usuarios deben ingresar en el elemento EditText. En los dispositivos con Android 4.2 (API nivel 17) o una versión posterior, puedes establecer el atributo android:labelFor del objeto View para indicar esta relación.

En el siguiente fragmento, se muestra un ejemplo de cómo etiquetar estos pares de elementos:


<!-- Label text for en-US locale would be "Username:" -->
<TextView
   android:id="@+id/usernameLabel" ...
   android:text="@string/username"
   android:labelFor="@+id/usernameEntry" />

<EditText
   android:id="@+id/usernameEntry" ... />

<!-- Label text for en-US locale would be "Password:" -->
<TextView
   android:id="@+id/passwordLabel" ...
   android:text="@string/password
   android:labelFor="@+id/passwordEntry" />

<EditText
   android:id="@+id/passwordEntry"
   android:inputType="textPassword" ... />

Elementos de una colección

Cuando agregas etiquetas a los elementos de una colección, cada etiqueta debe ser única. De esa manera, los servicios de accesibilidad del sistema pueden hacer referencia a exactamente un elemento en la pantalla cuando leen una etiqueta. Esta correspondencia permite que los usuarios sepan cuándo completaron el ciclo de la IU o cuándo trasladaron el enfoque a un elemento que ya descubrieron.

En particular, debes incluir texto adicional o información contextual en los elementos dentro de diseños reutilizados, como los objetos RecyclerView, a fin de que cada elemento secundario se pueda identificar de manera única.

Para ello, establece la descripción del contenido como parte de tu implementación del adaptador, como se muestra en el siguiente fragmento de código:

Kotlin

data class MovieRating(val title: String, val starRating: Integer)

class MyMovieRatingsAdapter(private val myData: Array<MovieRating>):
        RecyclerView.Adapter<MyMovieRatingsAdapter.MyRatingViewHolder>() {

    class MyRatingViewHolder(val ratingView: ImageView) :
            RecyclerView.ViewHolder(ratingView)

    override fun onBindViewHolder(holder: MyRatingViewHolder, position: Int) {
        val ratingData = myData[position]
        holder.ratingView.contentDescription = "Movie ${position}: " +
                "${ratingData.title}, ${ratingData.starRating} stars"
    }
}

Java

public class MovieRating {
    private String title;
    private int starRating;
    // ...
    public String getTitle() { return title; }
    public int getStarRating() { return starRating; }
}

public class MyMovieRatingsAdapter
        extends RecyclerView.Adapter<MyAdapter.MyRatingViewHolder> {
    private MovieRating[] myData;

    public static class MyRatingViewHolder extends RecyclerView.ViewHolder {
        public ImageView ratingView;
        public MyRatingViewHolder(ImageView iv) {
            super(iv);
            ratingView = iv;
        }
    }

    @Override
    public void onBindViewHolder(MyRatingViewHolder holder, int position) {
        MovieRating ratingData = myData[position];
        holder.ratingView.setContentDescription("Movie " + position + ": " +
                ratingData.getTitle() + ", " + ratingData.getStarRating() +
                " stars")
    }
}

Grupos de contenido relacionado

Si tu app muestra varios elementos de la IU que forman un grupo natural, como detalles de una canción o atributos de un mensaje, organiza estos elementos dentro de un contenedor, que generalmente es una subclase de ViewGroup. Establece el atributo android:screenReaderFocusable del objeto del contenedor en true y el atributo android:focusable de cada objeto interno en false. De este modo, los servicios de accesibilidad pueden presentar las descripciones del contenido de los elementos internos, una después de la otra, en un solo anuncio. Esta consolidación de elementos relacionados ayuda a los usuarios de la tecnología de accesibilidad a descubrir la información que se muestra en la pantalla de manera más eficiente.

El siguiente fragmento incluye elementos de contenido que se relacionan entre sí. Por ello, el elemento de contenedor, una instancia de ConstraintLayout, tiene su atributo android:screenReaderFocusable establecido en true y cada uno de los elementos TextView internos tiene su atributo android:focusable establecido en false:

<!-- In response to a single user interaction, accessibility services announce
     both the title and the artist of the song. -->
<ConstraintLayout
    android:id="@+id/song_data_container" ...
    android:screenReaderFocusable="true">

    <TextView
        android:id="@+id/song_title" ...
        android:focusable="false"
        android:text="@string/my_song_title" />
    <TextView
        android:id="@+id/song_artist"
        android:focusable="false"
        android:text="@string/my_songwriter" />
</ConstraintLayout>

Debido a que los servicios de accesibilidad anuncian las descripciones de los elementos internos en una sola frase, es importante que cada descripción sea lo más breve posible y, al mismo tiempo, transmita el significado del elemento.

Etiqueta de grupo personalizado

Si lo deseas, puedes anular la agrupación y el orden predeterminados de la plataforma de descripciones de los elementos internos de un grupo. Para ello, proporciona una descripción de contenido para el grupo.

En el siguiente fragmento, se muestra un ejemplo de una descripción de grupo personalizada:

<!-- In response to a single user interaction, accessibility services
     announce the custom content description for the group. -->
<ConstraintLayout
    android:id="@+id/song_data_container" ...
    android:screenReaderFocusable="true"
    android:contentDescription="@string/title_artist_best_song">

    <TextView
        android:id="@+id/song_title" ...

        <!-- Content ignored by accessibility services -->
        android:text="@string/my_song_title" />
    <TextView
        android:id="@+id/song_artist"

        <!-- Content ignored by accessibility services -->
        android:text="@string/my_songwriter" />
</ConstraintLayout>

Grupos anidados

Si la interfaz de tu app presenta información multidimensional, como una lista diaria de eventos de un festival, usa el atributo android:screenReaderFocusable en los contenedores del grupo interno. Este esquema de etiquetas ofrece un buen equilibrio entre la cantidad de anuncios necesarios para descubrir el contenido de la pantalla y la longitud de cada anuncio.

En el siguiente fragmento, se muestra un método de grupos de etiquetado dentro de grupos de mayor tamaño:

<!-- In response to a single user interaction, accessibility services
     announce the events for a single stage only. -->
<ConstraintLayout
    android:id="@+id/festival_event_table" ... >
    <ConstraintLayout
        android:id="@+id/stage_a_event_column"
        android:screenReaderFocusable="true">

        <!-- UI elements that describe the events on Stage A. -->

    </ConstraintLayout>
    <ConstraintLayout
        android:id="@+id/stage_b_event_column"
        android:screenReaderFocusable="true">

        <!-- UI elements that describe the events on Stage B. -->

    </ConstraintLayout>
</ConstraintLayout>

Encabezados dentro de texto

Algunas apps usan encabezados para resumir grupos de texto que se muestran en la pantalla. Si un elemento View específico representa un encabezado, puedes indicar su objetivo para los servicios de accesibilidad. Para ello, establece el atributo android:accessibilityHeading del elemento en true.

Los usuarios de los servicios de accesibilidad pueden elegir navegar entre encabezados, en lugar de hacerlo entre párrafos o palabras. Esta flexibilidad mejora la experiencia de navegación del texto.

Títulos del panel de accesibilidad

En Android 9 (API nivel 28) y versiones posteriores, puedes proporcionar títulos accesibles para los paneles de una pantalla. Para los fines de la accesibilidad, un panel es una parte de una ventana distinta a nivel visual, como el contenido de un fragmento. Si deseas que los servicios de accesibilidad comprendan cómo un panel se comporta de manera similar a una ventana, debes proporcionar títulos descriptivos para los paneles de tu app. Luego, los servicios de accesibilidad pueden proporcionar información más detallada a los usuarios cuando la apariencia o el contenido de un panel cambian.

Para especificar el título de un panel, usa el atributo android:accessibilityPaneTitle, como se muestra en el siguiente fragmento:

<!-- Accessibility services receive announcements about content changes
     that are scoped to either the "shopping cart view" section (top) or
     "browse items" section (bottom) -->
<MyShoppingCartView
     android:id="@+id/shoppingCartContainer"
     android:accessibilityPaneTitle="@string/shoppingCart" ... />

<MyShoppingBrowseView
     android:id="@+id/browseItemsContainer"
     android:accessibilityPaneTitle="@string/browseProducts" ... />

Elementos decorativos

Si un elemento de tu IU solo existe para brindar espacio visual o mejorar la apariencia, establece su atributo android:contentDescription en "null".

Si tu app solo admite dispositivos con Android 4.1 (API nivel 16) y versiones posteriores, puedes establecer los atributos android:importantForAccessibility de estos elementos meramente decorativos en "no".

Extiende los widgets del sistema

Punto clave: Cuando diseñes la IU de tu app, usa o extiende los widgets proporcionados por el sistema que estén lo más abajo posible en la jerarquía de clases de Android. Los widgets proporcionados por el sistema que están muy por debajo de la jerarquía ya tienen la mayoría de las capacidades de accesibilidad que necesita tu app. Es más fácil extender estos widgets que crear unos nuevos de las clases más genéricas View, ViewCompat, Canvas y CanvasCompat.

Si debes extender View o Canvas directamente, lo que podría ser necesario en niveles de juegos o experiencias muy personalizadas, consulta Cómo mejorar la accesibilidad de las vistas personalizadas.

En esta sección, se describe cómo implementar un tipo especial de Switch llamado TriSwitch. Un objeto TriSwitch funciona de manera similar a un objeto Switch, excepto que cada instancia de TriSwitch le permite al usuario alternar entre 3 estados posibles.

Extiende desde la jerarquía de clases

El objeto Switch hereda de varias clases de IU del framework en su jerarquía:

View
↳ TextView
  ↳ Button
    ↳ CompoundButton
      ↳ Switch

Lo ideal es que la nueva clase TriSwitch se extienda directamente desde la clase Switch. De esta manera, el framework de accesibilidad de Android proporciona la mayoría de las capacidades de accesibilidad que necesita la clase TriSwitch:

  • Acciones de accesibilidad: Informan al sistema cómo los servicios de accesibilidad emulan cada entrada de usuario posible que se realiza en un objeto TriSwitch (heredado de View).
  • Eventos de accesibilidad: Informan a los servicios de accesibilidad sobre todas las formas en que las que puede cambiar la apariencia de un objeto TriSwitch cuando la pantalla se vuelve a cargar o se actualiza (heredado de View).
  • Características: Son detalles sobre cada objeto TriSwitch, como el contenido de cualquier texto que muestra (heredado de TextView).
  • Información de estado: Es la descripción del estado de un objeto TriSwitch en un determinado momento, como "marcado" o "desmarcado" (heredado de CompoundButton).
  • Descripción de texto del estado: Es una explicación basada en texto de lo que representa cada estado (heredado de Switch).

Este comportamiento agregado, proveniente de Switch y sus superclases, es prácticamente el comportamiento deseado de los objetos TriSwitch. Por lo tanto, tu implementación puede enfocarse en expandir la cantidad de estados posibles de 2 a 3.

Define eventos personalizados

Cuando extiendes un widget del sistema, es probable que cambies algún aspecto de la manera en la que los usuarios interactúan con él. Es importante definir estos cambios de interacción para que los servicios de accesibilidad puedan actualizar el widget de tu app como si el usuario interactuara directamente con él.

Como lineamiento general, para cada devolución de llamada basada en vistas que anules, debes volver a definir la acción de accesibilidad correspondiente anulando ViewCompat.replaceAccessibilityAction(). Durante las pruebas de la app, puedes llamar a ViewCompat.performAccessibilityAction() para validar el comportamiento de estas acciones redefinidas.

Cómo funcionaría este principio para los objetos TriSwitch

A diferencia de un objeto Switch común, presionar un objeto TriSwitch cambia entre 3 estados posibles. Por lo tanto, la acción de accesibilidad ACTION_CLICK correspondiente debe actualizarse:

Kotlin

class TriSwitch(context: Context) : Switch(context) {
    // 0, 1, or 2.
    var currentState: Int = 0
        private set

    init {
        updateAccessibilityActions()
    }

    private fun updateAccessibilityActions() {
        ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
            action-label) {
            view, args -> moveToNextState()
        })
    }

    private fun moveToNextState() {
        currentState = (currentState + 1) % 3
    }
}

Java

public class TriSwitch extends Switch {
    // 0, 1, or 2.
    private int currentState;

    public int getCurrentState() {
        return currentState;
    }

    public TriSwitch() {
        updateAccessibilityActions();
    }

    private void updateAccessibilityActions() {
        ViewCompat.replaceAccessibilityAction(this, ACTION_CLICK,
            action-label, (view, args) -> moveToNextState());
    }

    private void moveToNextState() {
        currentState = (currentState + 1) % 3;
    }
}

Utiliza señales que no hagan uso del color

A fin de ayudar a los usuarios daltónicos, utiliza señales que no requieran el uso del color para distinguir elementos de la IU dentro de las pantallas de tu app. Algunas de estas técnicas consisten en usar diferentes formas o tamaños, mostrar patrones visuales o de texto, o agregar respuesta táctil o de audio para identificar las diferencias entre los elementos.

En la figura 1, se muestran dos versiones de una actividad. Una versión solo usa color para distinguir entre dos acciones posibles en un flujo de trabajo. La otra versión usa la práctica recomendada de incluir formas y texto además de color para destacar las diferencias entre las dos opciones:

Figura 1: Ejemplos de cómo crear elementos de la IU usando color únicamente (izquierda) y usando color, formas y texto (derecha)

Mejora la accesibilidad del contenido multimedia

Si estás desarrollando una app que incluye contenido multimedia, como un clip de video o una grabación de audio, asegúrate de que los usuarios con diferentes tipos de necesidades de accesibilidad puedan comprender el material. En particular, te recomendamos que hagas lo siguiente:

  • Incluye controles que les permitan a los usuarios pausar o detener el contenido multimedia, cambiar el volumen y activar o desactivar los subtítulos.
  • Si en un video se presenta información fundamental para completar un flujo de trabajo, proporciona el mismo contenido en un formato alternativo, como una transcripción.

Recursos adicionales

Si deseas obtener más información sobre cómo mejorar la accesibilidad de tu app, consulta los siguientes recursos adicionales:

Codelabs

Entradas de blog