Principes pour améliorer l'accessibilité des applications

Pour aider les utilisateurs ayant des besoins d'accessibilité, le framework Android vous permet de créer un service d'accessibilité qui peut présenter du contenu d'applications aux utilisateurs et les utiliser en leur nom.

Android fournit plusieurs services d'accessibilité, y compris :

Pour aider les personnes ayant des besoins d'accessibilité à utiliser votre application, votre application doit suivre les bonnes pratiques décrites sur cette page, qui s'appuient sur les consignes décrites dans le guide Rendre les applications plus accessibles.

Chacune des bonnes pratiques suivantes, décrites dans les sections ci-dessous, peut améliorer davantage l'accessibilité de votre application :

Libellés
Les utilisateurs doivent pouvoir comprendre le contenu et l'objectif de chaque élément d'interface utilisateur interactif et pertinent de votre application.
Ajouter des actions d'accessibilité
En ajoutant des actions d'accessibilité, vous pouvez permettre aux utilisateurs de services d'accessibilité de suivre des parcours utilisateur critiques dans votre application.
Utiliser les fonctionnalités d'accessibilité intégrées
Compose propose de nombreux comportements d'accessibilité par défaut. Profitez des comportements d'accessibilité prédéfinis pour rendre vos composants accessibles avec peu ou pas de travail supplémentaire. Compose fournit également des moyens de répondre à des exigences d'accessibilité plus spécifiques qui ne sont pas couvertes par les fonctionnalités par défaut.
Utiliser des signaux autres que la couleur
Les utilisateurs doivent pouvoir distinguer clairement les catégories d'éléments dans une UI. Pour ce faire, exprimez ces différences à l'aide de motifs, de positions et de couleurs.
Rendre les contenus multimédias plus accessibles
Ajoutez des descriptions au contenu vidéo ou audio de votre application, afin que les utilisateurs qui consultent ce contenu n'aient pas besoin de se référer à des indicateurs visuels ou auditifs.

Libellés

Il est important de fournir aux utilisateurs des libellés utiles et descriptifs pour chaque élément d'interface utilisateur interactif de votre application. Chaque libellé doit expliquer la sémantique d'un élément particulier, c'est-à-dire sa signification et son objectif. Les lecteurs d'écran tels que TalkBack peuvent annoncer ces libellés aux utilisateurs.

Dans la plupart des cas, les API Compose et Material sont compatibles avec l'accessibilité par défaut . Toutefois, si vous devez spécifier manuellement les propriétés sémantiques d'un élément d'UI, utilisez le modificateur semantics et la propriété contentDescription. Pour en savoir plus sur la sémantique, consultez la section Sémantique.

Les sections suivantes décrivent plusieurs autres techniques de libellé.

Éléments modifiables

Lorsque vous ajoutez des libellés à des éléments modifiables, tels que des champs de texte, il peut être utile d'afficher des exemples d'entrées valides au niveau de l'élément, et de rendre ces exemples disponibles pour les lecteurs d'écran. Dans ce cas, vous pouvez utiliser un texte d'espace réservé, également appelé texte d'aide.

Dans l'exemple suivant, le TextField comporte un paramètre placeholder qui fournit un texte d'aide.

val usernameState = rememberTextFieldState()
TextField(
    state = usernameState,
    lineLimits = TextFieldLineLimits.SingleLine,
    placeholder = { Text("Enter Username") }
)

Il est également courant qu'un champ de texte comporte un libellé descriptif correspondant qui décrit ce que les utilisateurs doivent saisir comme entrée.

Dans l'exemple suivant, le TextField comporte un paramètre label qui fournit une description d'accessibilité.

TextField(
    state = rememberTextFieldState(initialText = "Hello"),
    label = { Text("Label") }
)

Pour en savoir plus sur le texte et les entrées utilisateur, consultez la section Configurer des champs de texte.

Éléments d'une collection

Lorsque vous ajoutez des libellés aux éléments d'une collection, chaque libellé doit être unique. Ainsi, les services d'accessibilité du système peuvent faire référence à un seul élément à l'écran lors de l'annonce d'un libellé. Cette correspondance permet aux utilisateurs de savoir quand ils parcourent l'UI ou lorsqu'ils déplacent le focus vers un élément qu'ils ont déjà découvert.

Par exemple, lorsque vous avez un LazyColumn ou un LazyRow, utilisez le modificateur semantics pour attribuer un collectionItemInfo unique à chaque élément, comme indiqué dans l'extrait suivant :

MilkyWayList(
    modifier = Modifier
        .semantics {
            collectionInfo = CollectionInfo(
                rowCount = milkyWay.count(),
                columnCount = 1
            )
        }
) {
    milkyWay.forEachIndexed { index, text ->
        Text(
            text = text,
            modifier = Modifier.semantics {
                collectionItemInfo =
                    CollectionItemInfo(index, 0, 0, 0)
            }
        )
    }
}

Pour en savoir plus sur les propriétés sémantiques des listes et des grilles, consultez la section Informations sur les listes et les éléments.

Groupes de contenus similaires

Si votre application affiche plusieurs éléments d'interface utilisateur qui constituent un groupe naturel, tels que les informations d'une chanson ou les attributs d'un message, organisez-les dans un conteneur parent (comme Column, Row ou Box). Utilisez le modificateur semantics du conteneur parent pour définir mergeDescendants sur true.

Les services d'accessibilité peuvent ainsi présenter à la suite les descriptions des éléments internes dans une seule annonce. La consolidation des éléments associés permet aux utilisateurs de technologies d'assistance de découvrir plus efficacement les informations affichées à l'écran.

Dans l'extrait suivant, le composable Row fait office de conteneur parent. Dans le Row se trouvent des éléments associés qui affichent des métadonnées pour un article de blog : l'avatar de l'auteur, son nom et le temps de lecture estimé. Définir mergeDescendants sur true regroupe ces éléments internes, de sorte que les services d'accessibilité peuvent les traiter comme une seule unité.

@Composable
private fun PostMetadata(metadata: Metadata) {
    // Merge elements below for accessibility purposes
    Row(modifier = Modifier.semantics(mergeDescendants = true) {}) {
        Image(
            imageVector = Icons.Filled.AccountCircle,
            contentDescription = null // decorative
        )
        Column {
            Text(metadata.author.name)
            Text("${metadata.date}${metadata.readTimeMinutes} min read")
        }
    }
}

Lorsque vous regroupez des éléments associés comme dans l'exemple précédent, ne rendez interactif que le conteneur parent. Évitez d'ajouter des modificateurs clickable ou focusable aux éléments enfants internes. Appliquez plutôt les modificateurs au Row ou Column parent.

Étant donné que les services d'accessibilité annoncent les descriptions des éléments intérieurs en une seule fois, il est important que chaque description soit aussi courte que possible tout en transmettant correctement la signification de l'élément.

Remarque : En général, lorsque vous créez une description de contenu pour un groupe, évitez d'agréger le texte de ses enfants. Cela rend la description du groupe fragile, et lorsque le texte d'un enfant change, la description du groupe peut ne plus correspondre au texte visible.

Dans un contexte de liste ou de grille, un lecteur d'écran peut consolider le texte des nœuds de texte enfants d'un élément de liste ou de grille. Il est préférable d'éviter de modifier cette annonce.

Pour en savoir plus sur la fusion de la sémantique, consultez la section Fusion et suppression.

Titres dans le texte

Certaines applications utilisent des titres pour récapituler les groupes de texte qui apparaissent à l'écran. Si un élément particulier représente un titre, vous pouvez indiquer son objectif aux services d'accessibilité en définissant la propriété heading dans le modificateur semantics.

@Composable
private fun Subsection(text: String) {
    Text(
        text = text,
        style = MaterialTheme.typography.headlineSmall,
        modifier = Modifier.semantics { heading() }
    )
}

Les utilisateurs de services d'accessibilité peuvent choisir de naviguer d'un titre à l'autre plutôt que d'un paragraphe/mot à un autre. Cette flexibilité améliore l'expérience de navigation dans le texte.

Pour en savoir plus sur la propriété sémantique heading, consultez la section Titres.

Titres accessibles pour les volets

Sous Android 9 (niveau d'API 28) ou version ultérieure, vous pouvez fournir des titres accessibles pour les volets d'un écran. Pour des raisons d'accessibilité, un volet est une partie distincte d'une fenêtre.

Pour permettre aux services d'accessibilité de comprendre le comportement d'un volet, attribuez des titres descriptifs aux volets de votre application. Les services d'accessibilité peuvent ensuite fournir des informations plus précises aux utilisateurs lorsque l'apparence ou le contenu d'un volet changent.

ShareSheet(
    message = "Choose how to share this photo",
    modifier = Modifier
        .fillMaxWidth()
        .align(Alignment.TopCenter)
        .semantics { paneTitle = "New bottom sheet" }
)

Pour en savoir plus sur la propriété sémantique paneTitle, consultez la section Composants de type fenêtre.

Éléments décoratifs

Si un élément de votre UI n'existe qu'à des fins d'espacement ou d'apparence visuelle, définissez les propriétés appropriées sur l'élément pour indiquer que les services d'accessibilité peuvent l'ignorer.

Pour les composables Image ou Icon, définissez contentDescription = null. Pour les autres éléments purement décoratifs qui ne fournissent aucun contexte ni aucune fonctionnalité, vous pouvez utiliser hideFromAccessibility. Cette propriété sémantique indique aux services d'accessibilité d'ignorer l'élément.

Si un composable interactif contient des éléments enfants décoratifs et non interactifs, utilisez clearAndSetSemantics pour vous assurer que les services d'accessibilité ne les parcourent pas. Notez que clearAndSetSemantics efface complètement la sémantique par défaut d'un élément et de ses enfants. Cela vous permet de définir un nouvel élément d'accessibilité unifié. En règle générale, vous utilisez cette approche pour les composants personnalisés complexes.

Dans l'exemple suivant, Icon et Text sont des éléments enfants décoratifs dans un bouton à bascule personnalisé. Pour empêcher les services d'accessibilité de parcourir ces enfants individuellement, vous pouvez effacer leur sémantique à l'aide de clearAndSetSemantics sur le Row parent. Cela indique aux services d'accessibilité de traiter l'ensemble du Row comme un bouton à bascule parcourable :

// Developer might intend this to be a toggleable.
// Using `clearAndSetSemantics`, on the Row, a clickable modifier is applied,
// a custom description is set, and a Role is applied.

@Composable
fun FavoriteToggle() {
    val checked = remember { mutableStateOf(true) }
    Row(
        modifier = Modifier
            .toggleable(
                value = checked.value,
                onValueChange = { checked.value = it }
            )
            .clearAndSetSemantics {
                stateDescription = if (checked.value) "Favorited" else "Not favorited"
                toggleableState = ToggleableState(checked.value)
                role = Role.Switch
            },
    ) {
        Icon(
            imageVector = Icons.Default.Favorite,
            contentDescription = null // not needed here

        )
        Text("Favorite?")
    }
}

Pour en savoir plus sur l'effacement de la sémantique, consultez la section Effacer et définir la sémantique.

Ajouter des actions d'accessibilité

Il est important de s'assurer que les utilisateurs de services d'accessibilité peuvent suivre tous les parcours utilisateur dans votre application.

Si l'interaction de votre composable personnalisé modifie l'état de l'application d'une manière qui n'est pas évidente, fournissez des libellés descriptifs pour les actions de pression standard à l'aide de paramètres tels que onClickLabel ou onLongClickLabel dans Modifier.clickable ou Modifier.combinedClickable.

Pour les interactions complexes qui ne peuvent pas être mappées sur des pressions standard, utilisez customActions.

Par exemple, si votre application permet aux utilisateurs de faire glisser un élément vers un autre emplacement ou de balayer un élément dans une liste, vous pouvez fournir un autre moyen de suivre ces parcours utilisateur en exposant l'action aux services d'accessibilité. Ainsi, les utilisateurs de TalkBack, Voice Access ou Switch Access peuvent effectuer des actions qui ne seraient autrement disponibles que par des gestes.

Dans Compose, vous pouvez définir des actions d'accessibilité personnalisées via la propriété customActions dans le modificateur semantics, à l'aide de CustomAccessibilityAction.

Par exemple, si votre application permet aux utilisateurs de balayer un élément pour le supprimer, vous pouvez exposer cette fonctionnalité via une action d'accessibilité personnalisée :

SwipeToDismissBox(
    modifier = Modifier.semantics {
        // Represents the swipe to dismiss for accessibility
        customActions = listOf(
            CustomAccessibilityAction(
                label = "Remove article from list",
                action = {
                    removeArticle()
                    true
                }
            )
        )
    },
    state = rememberSwipeToDismissBoxState(),
    backgroundContent = {}
) {
    ArticleListItem()
}

Une fois l'action d'accessibilité personnalisée implémentée, les utilisateurs peuvent accéder à l'action via le menu d'actions.

Pour en savoir plus sur les actions personnalisées, consultez la section Actions personnalisées.

Rendre les actions disponibles compréhensibles

Lorsqu'un élément d'interface utilisateur est compatible avec des actions telles que l'appui de manière prolongée, un service d'accessibilité comme TalkBack l'annonce comme suit : "Appuyez deux fois et maintenez pour appuyer de manière prolongée".

Cette annonce générique ne donne pas de contexte à l'utilisateur sur ce que fait un appui prolongé.

Pour rendre cette annonce plus utile, spécifiez une description significative pour l'action.

Dans Compose, les modificateurs d'interaction standard tels que clickable et combinedClickable comportent des paramètres intégrés (à savoir onClickLabel et onLongClickLabel) que vous pouvez utiliser pour fournir des descriptions des actions, comme dans l'exemple suivant :

var contextMenuPhotoId by rememberSaveable { mutableStateOf<Int?>(null) }
val haptics = LocalHapticFeedback.current
LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 128.dp)) {
    items(photos, { it.id }) { photo ->
        ImageItem(
            photo,
            Modifier
                .combinedClickable(
                    onClick = { activePhotoId = photo.id },
                    onLongClick = {
                        haptics.performHapticFeedback(HapticFeedbackType.LongPress)
                        contextMenuPhotoId = photo.id
                    },
                    onLongClickLabel = stringResource(R.string.open_context_menu)
                )
        )
    }
}
if (contextMenuPhotoId != null) {
    PhotoActionsSheet(
        photo = photos.first { it.id == contextMenuPhotoId },
        onDismissSheet = { contextMenuPhotoId = null }
    )
}

L'annonce TalkBack devient alors : "Ouvrir le menu contextuel", ce qui aide les utilisateurs à comprendre l'objectif de cette action.

Vous pouvez également spécifier un libellé directement dans le modificateur semantics.

Pour en savoir plus sur la réponse aux pressions et aux clics, consultez les sections Appuyer et cliquer et Éléments interactifs.

Utiliser les fonctionnalités d'accessibilité intégrées

Lorsque vous concevez l'UI de votre application, profitez des fonctionnalités d'accessibilité intégrées pour éviter de réimplémenter des fonctionnalités déjà existantes. Les API Material, Compose UI et Foundation implémentent et proposent de nombreuses pratiques accessibles par défaut.

Dans Jetpack Compose, utilisez des composables intégrés tels que Button, Switch et Checkbox pour créer des UI accessibles. Ces composants sont préemballés avec des modificateurs semantics, tels que role et stateDescription, que vous pouvez utiliser pour rendre vos applications plus accessibles.

Appliquer la sémantique aux composants personnalisés

Lorsque vous créez un composant personnalisé, tenez compte du type de compatibilité avec l'accessibilité dont ce composant a besoin pour remplir son rôle. Souvent, les API Compose standard que vous utilisez déjà, telles que clickable, toggleable ou selectable, sont suffisantes, car elles remplissent automatiquement l'arborescence sémantique pour vous.

Toutefois, certains composants nécessitent des informations plus spécifiques que celles fournies par les modificateurs standard. Dans ce cas, recherchez des modificateurs spécialisés (comme triStateToggleable) ou, s'il n'en existe aucun, fournissez explicitement la sémantique à l'aide du Modifier.semantics de bas niveau.

Prenons l'exemple d'un TriStateSwitch, un commutateur à trois états (activé, désactivé et indéterminé).

Alors qu'un modificateur toggleable standard suppose deux états, le modificateur triStateToggleable gère la complexité du troisième état. Il définit automatiquement le Role d'accessibilité (Switch) et l'State. Ainsi, les services d'accessibilité reçoivent des informations précises, et vous n'avez pas besoin de définir manuellement la sémantique.

L'extrait de code suivant montre un TriStateSwitch utilisant cette approche :

@Composable
fun TriStateSwitch(
    state: ToggleableState,
    onClick: () -> Unit,
    modifier: Modifier = Modifier
) {
    // A real implementation would include custom drawing for the switch.
    // This example uses a Box to demonstrate the semantics.
    Box(
        modifier = modifier
            .size(width = 64.dp, height = 40.dp)
            // triStateToggleable handles the semantics (Role and State)
            // automatically, so explicit Modifier.semantics is not needed here.
            .triStateToggleable(
                state = state,
                onClick = onClick,
                role = Role.Switch
            )
            // Add visual feedback based on the state
            .background(
                when (state) {
                    ToggleableState.On -> Color.Green
                    ToggleableState.Off -> Color.Gray
                    ToggleableState.Indeterminate -> Color.Yellow
                }
            )
    )
}

// Usage within another composable:
var state by remember { mutableStateOf(ToggleableState.Off) }
TriStateSwitch(
    state = state,
    onClick = {
        state = when (state) {
            ToggleableState.Off -> ToggleableState.Indeterminate
            ToggleableState.Indeterminate -> ToggleableState.On
            ToggleableState.On -> ToggleableState.Off
        }
    }
)

Lorsque vous créez un composant personnalisé, assurez-vous de fournir toutes les propriétés sémantiques pertinentes à des fins d'accessibilité. Par exemple, si votre composant imite un contrôle standard tel qu'un commutateur ou un bouton, ces propriétés incluent le rôle du composant (tel que Role.Switch ou Role.Button), stateDescription (tel que "Activé", "Désactivé", "Coché" ou "Non coché") et tous les libellés d'action pertinents. Pour en savoir plus, consultez la section Composants personnalisés.

Utiliser des signaux autres que la couleur

Pour aider les utilisateurs qui ne distinguent pas bien les couleurs, utilisez des signaux autres que la couleur pour séparer les éléments d'UI sur les écrans de votre application. Vous pouvez par exemple utiliser différentes formes ou tailles, fournir du texte ou des motifs visuels, ou ajouter un retour audio ou tactile (haptique) pour marquer les différences entre ces éléments.

La figure 1 illustre deux versions d'une activité. Une version n'utilise que la couleur pour distinguer deux actions possibles dans un workflow. L'autre version applique la bonne pratique qui consiste à inclure des formes et du texte en plus de la couleur pour mettre en évidence les différences entre les deux options :

À gauche se trouve un écran avec deux boutons circulaires, l&#39;un vert et l&#39;autre rouge. À droite, le même écran, mais les deux boutons circulaires sont étiquetés avec du texte et des icônes explicites.
Image 1. Exemples de création d'éléments d'UI en utilisant uniquement de la couleur (à gauche) ou des couleurs, des formes et du texte (à droite).

Rendre les contenus multimédias plus accessibles

Si vous développez une application qui inclut du contenu multimédia, comme un extrait vidéo ou un enregistrement audio, essayez d'aider les utilisateurs ayant différents types de besoins d'accessibilité à comprendre le contenu. En particulier, essayez de procéder comme suit :

  • inclure des commandes permettant aux utilisateurs de mettre en pause ou d'arrêter la lecture d'un contenu multimédia, de régler le volume et d'activer ou de désactiver les sous-titres ;
  • si une vidéo présente des informations essentielles pour un workflow, fournir le même contenu dans un autre format, par exemple une transcription.

Ressources supplémentaires

Pour en savoir plus sur l'amélioration de l'accessibilité de votre application, consultez les ressources supplémentaires suivantes :

Ateliers de programmation

Afficher le contenu