Per assistere gli utenti con esigenze di accessibilità, il framework Android ti consente di creare un servizio di accessibilità in grado di presentare agli utenti i contenuti delle app e di utilizzare le app per loro conto.
Android offre diversi servizi di accessibilità di sistema, tra cui:
- TalkBack: aiuta le persone ipovedenti o cieche. Annuncia i contenuti tramite una voce sintetizzata ed esegue azioni su un'app in risposta alle attivazioni dell'utente.
- Switch Access: aiuta le persone con disabilità motorie. Evidenzia gli elementi interattivi ed esegue azioni in risposta alla pressione di un pulsante da parte dell'utente. Consente di controllare il dispositivo utilizzando solo uno o due pulsanti.
Per aiutare le persone con esigenze di accessibilità a utilizzare la tua app con successo, l'app deve seguire le best practice descritte in questa pagina, che si basano sulle linee guida descritte in Rendi le app più accessibili.
Ognuna di queste best practice, descritte nelle sezioni seguenti, può migliorare ulteriormente l'accessibilità della tua app:
- Etichetta gli elementi
- Gli utenti devono essere in grado di comprendere i contenuti e lo scopo di ogni elemento UI interattivo e significativo all'interno della tua app.
- Aggiungi azioni di accessibilità
- Aggiungendo azioni di accessibilità, puoi consentire agli utenti dei servizi di accessibilità di completare flussi utente critici all'interno della tua app.
- Utilizza le funzioni di accessibilità integrate
- Compose offre molti comportamenti di accessibilità per impostazione predefinita. Sfrutta i comportamenti di accessibilità predefiniti per rendere i tuoi componenti accessibili con un lavoro aggiuntivo minimo o nullo. Compose offre anche modi per supportare requisiti di accessibilità più specifici non coperti dalle funzionalità predefinite.
- Utilizza indicatori diversi dal colore
- Gli utenti devono essere in grado di distinguere chiaramente tra le categorie di elementi in un'interfaccia utente. Per farlo, utilizza pattern e posizione, oltre al colore, per esprimere queste differenze.
- Rendi i contenuti multimediali più accessibili
- Aggiungi descrizioni ai contenuti video o audio della tua app in modo che gli utenti che li utilizzano non debbano fare affidamento su segnali interamente visivi o uditivi.
Elementi delle etichette
È importante fornire agli utenti etichette utili e descrittive per ogni elemento UI interattivo della tua app. Ogni etichetta deve spiegare la semantica di un determinato elemento, ovvero il significato e lo scopo dell'elemento. Gli screen reader come TalkBack possono annunciare queste etichette agli utenti.
Nella maggior parte dei casi, le API Compose e Material dispongono di un supporto per l'accessibilità predefinito. Tuttavia, se devi specificare manualmente le proprietà semantiche di un elemento UI, utilizza il modificatore semantics e la proprietà contentDescription. Per saperne di più sulla semantica, consulta Semantica.
Le sezioni seguenti descrivono diverse altre tecniche di etichettatura.
Elementi modificabili
Quando assegni un'etichetta a elementi modificabili, come i campi di testo, è utile mostrare un testo che fornisca un esempio di input valido nell'elemento stesso, oltre a rendere questo testo di esempio disponibile per gli screen reader. In queste situazioni, puoi utilizzare il testo segnaposto, chiamato anche testo di suggerimento.
Nell'esempio seguente, TextField ha un parametro placeholder che fornisce il testo del suggerimento.
val usernameState = rememberTextFieldState() TextField( state = usernameState, lineLimits = TextFieldLineLimits.SingleLine, placeholder = { Text("Enter Username") } )
È anche comune che un campo di testo abbia un'etichetta descrittiva corrispondente che descrive ciò che gli utenti devono inserire come input.
Nell'esempio seguente, TextField ha un parametro label che fornisce una descrizione dell'accessibilità.
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
Per saperne di più sul testo e sull'input dell'utente, consulta Configura i campi di testo.
Elementi in una raccolta
Quando aggiungi etichette agli elementi di una raccolta, ogni etichetta deve essere univoca. In questo modo, i servizi di accessibilità del sistema possono fare riferimento esattamente a un elemento sullo schermo quando annunciano un'etichetta. Questa corrispondenza consente agli utenti di sapere quando scorrono la UI o quando spostano lo stato attivo su un elemento che hanno già scoperto.
Ad esempio, se hai un LazyColumn o un LazyRow, utilizza il modificatore semantics per assegnare un collectionItemInfo univoco a ogni elemento, come mostrato nello snippet seguente:
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) } ) } }
Per ulteriori informazioni sulle proprietà semantiche per elenchi e griglie, consulta Informazioni su elenchi ed elementi.
Gruppi di contenuti correlati
Se la tua app mostra diversi elementi UI che formano un gruppo naturale, come i dettagli di un brano o gli attributi di un messaggio, disponili all'interno di un contenitore principale (come Column, Row o Box). Utilizza il modificatore semantics del contenitore principale per impostare mergeDescendants su true.
In questo modo, i servizi di accessibilità possono presentare le descrizioni dei contenuti degli elementi interni una dopo l'altra, in un unico annuncio. Il consolidamento degli elementi correlati aiuta gli utenti delle tecnologie per la disabilità a scoprire le informazioni sullo schermo in modo più efficiente.
Nello snippet seguente, il composable Row funge da contenitore principale.
All'interno di Row sono presenti elementi correlati che mostrano i metadati di un blog post: l'avatar dell'autore, il nome dell'autore e il tempo di lettura stimato.
L'impostazione di mergeDescendants su true raggruppa questi elementi interni, in modo che i servizi di accessibilità possano trattarli come un'unica 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") } } }
Quando raggruppi elementi correlati come nell'esempio precedente, rendi interattivo solo il contenitore principale. Evita di aggiungere modificatori clickable o focusable agli elementi secondari interni. Applica invece i modificatori all'elemento principale Row o Column.
Poiché i servizi di accessibilità annunciano le descrizioni degli elementi interni in un'unica espressione, è importante mantenere ogni descrizione il più breve possibile, pur trasmettendo il significato dell'elemento.
Nota:in generale, quando crei una descrizione dei contenuti per un gruppo, evita di aggregare il testo dei relativi elementi secondari. In questo modo, la descrizione del gruppo diventa fragile e, quando il testo di un elemento secondario cambia, la descrizione del gruppo potrebbe non corrispondere più al testo visibile.
In un contesto di elenco o griglia, uno screen reader potrebbe consolidare il testo dei nodi di testo secondari di un elemento di elenco o griglia. È meglio evitare di modificare questo annuncio.
Per saperne di più sulla semantica di unione, consulta Unione e cancellazione.
Intestazioni all'interno del testo
Alcune app utilizzano le intestazioni per riassumere i gruppi di testo visualizzati sullo schermo. Se un determinato elemento rappresenta un'intestazione, puoi indicarne lo scopo per i servizi di accessibilità impostando la proprietà heading nel modificatore semantics.
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
Gli utenti dei servizi di accessibilità possono scegliere di navigare tra le intestazioni anziché tra i paragrafi o tra le parole. Questa flessibilità migliora l'esperienza di navigazione del testo.
Per saperne di più sulla proprietà semantica heading, consulta Intestazioni.
Titoli dei riquadri di accessibilità
In Android 9 (livello API 28) e versioni successive, puoi fornire titoli accessibili per i riquadri di una schermata. Ai fini dell'accessibilità, un riquadro è una parte visivamente distinta di una finestra.
Affinché i servizi di accessibilità comprendano il comportamento simile a una finestra di un riquadro, assegna titoli descrittivi ai riquadri della tua app. I servizi di accessibilità possono quindi fornire informazioni più dettagliate agli utenti quando l'aspetto o i contenuti di un riquadro cambiano.
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
Per ulteriori informazioni sulla proprietà di semantica paneTitle, consulta
Componenti simili a finestre.
Elementi decorativi
Se un elemento della UI esiste solo per scopi di spaziatura o aspetto visivo, imposta le proprietà appropriate sull'elemento per indicare che i servizi di accessibilità possono ignorarlo.
Per i componibili Image o Icon, imposta contentDescription = null. Per altri elementi puramente decorativi che non forniscono contesto o funzionalità, puoi utilizzare hideFromAccessibility. Questa proprietà semantica indica ai servizi di accessibilità di ignorare l'elemento.
Se un composable interattivo contiene elementi secondari decorativi e non interattivi, utilizza clearAndSetSemantics per assicurarti che i servizi di accessibilità non li attraversino. Tieni presente che clearAndSetSemantics cancella completamente la semantica predefinita di un elemento e dei relativi elementi secondari. In questo modo puoi definire un nuovo elemento di accessibilità unificato. In genere, questo approccio viene utilizzato per componenti personalizzati complessi.
Nell'esempio seguente, Icon e Text sono elementi secondari decorativi
all'interno di un pulsante di attivazione/disattivazione personalizzato. Per impedire ai servizi di accessibilità di attraversare questi elementi secondari singolarmente, puoi cancellare la loro semantica utilizzando clearAndSetSemantics sull'elemento principale Row. In questo modo, i servizi di accessibilità
trattano l'intero Row come un pulsante di attivazione/disattivazione attraversabile:
// 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?") } }
Per saperne di più sulla cancellazione della semantica, consulta Cancella e imposta la semantica.
Aggiungi azioni di accessibilità
È importante assicurarsi che gli utenti dei servizi di accessibilità abbiano un modo per completare tutti i flussi utente nella tua app.
Se l'interazione del composable personalizzato modifica lo stato dell'app in un modo non ovvio, fornisci etichette descrittive per le azioni di tocco standard utilizzando parametri come onClickLabel o onLongClickLabel in Modifier.clickable o Modifier.combinedClickable.
Per interazioni complesse non mappabili ai tocchi standard, utilizza customActions.
Ad esempio, se la tua app consente agli utenti di trascinare un elemento in un'altra posizione o di scorrere un elemento in un elenco, puoi fornire un modo alternativo per completare questi flussi utente esponendo l'azione ai servizi di accessibilità. In questo modo, gli utenti di TalkBack, Voice Access o Switch Access possono eseguire azioni che altrimenti potrebbero essere disponibili solo tramite gesti.
In Compose, puoi definire azioni di accessibilità personalizzate tramite la proprietà customActions nel modificatore semantics, utilizzando CustomAccessibilityAction.
Ad esempio, se la tua app consente agli utenti di scorrere un elemento per ignorarlo, puoi esporre la funzionalità tramite un'azione di accessibilità personalizzata:
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() }
Con l'azione di accessibilità personalizzata implementata, gli utenti possono accedere all'azione tramite il menu Azioni.
Per saperne di più sulle azioni personalizzate, consulta Azioni personalizzate.
Rendere comprensibili le azioni disponibili
Quando un elemento UI supporta azioni come il tocco prolungato, un servizio di accessibilità come TalkBack lo annuncia come "Tocca due volte e tieni premuto per una pressione prolungata".
Questo annuncio generico non fornisce all'utente alcun contesto su ciò che fa un'azione di tocco e pressione.
Per rendere questo annuncio più utile, specifica una descrizione significativa per l'azione.
In Compose, i modificatori di interazione standard come clickable e
combinedClickable hanno parametri integrati (ovvero onClickLabel e
onLongClickLabel) che puoi utilizzare per fornire descrizioni delle azioni,
come nell'esempio seguente:
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 } ) }
In questo modo, TalkBack annuncia "Apri menu contestuale", aiutando gli utenti a comprendere lo scopo dell'azione.
Puoi anche specificare un'etichetta direttamente nel modificatore semantics.
Per saperne di più su come rispondere a tocchi e clic, consulta Tocca e premi ed Elementi interattivi.
Utilizza le funzioni di accessibilità integrate
Quando progetti la UI della tua app, sfrutta le funzionalità di accessibilità integrate per evitare di reimplementare funzionalità già esistenti. Le API Material, Compose UI e Foundation implementano e offrono molte pratiche accessibili per impostazione predefinita.
In Jetpack Compose, utilizza gli elementi componibili integrati come Button, Switch e Checkbox per creare UI accessibili. Questi componenti sono pre-pacchettizzati con modificatori semantics, come role e stateDescription, che puoi utilizzare per rendere le tue app più accessibili.
Applica la semantica ai componenti personalizzati
Quando crei un componente personalizzato, tieni presente il tipo di supporto per l'accessibilità richiesto da questo componente per svolgere il suo ruolo. Spesso, le API Compose standard che utilizzi già, come clickable, toggleable o selectable, sono sufficienti perché compilano automaticamente l'albero della semantica.
Tuttavia, alcuni componenti richiedono informazioni più specifiche di quelle fornite dai modificatori standard. In questi casi, cerca modificatori specializzati (come triStateToggleable) o, se non ne esistono, fornisci esplicitamente la semantica utilizzando Modifier.semantics di basso livello.
Ad esempio, considera un TriStateSwitch, un interruttore con tre stati (On, Off e Indeterminato).
Mentre un modificatore toggleable standard presuppone due stati, il modificatore triStateToggleable gestisce la complessità del terzo stato. Imposta automaticamente l'accessibilità Role (Switch) e State. In questo modo, i servizi di accessibilità ricevono informazioni accurate e non è necessario definire manualmente la semantica.
Il seguente snippet di codice mostra un TriStateSwitch che utilizza questo approccio:
@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 } } )
Quando crei un componente personalizzato, assicurati di fornire tutte le proprietà semantiche pertinenti per l'accessibilità. Ad esempio, se il componente imita un controllo standard come un interruttore o un pulsante, queste proprietà includono il ruolo del componente (ad esempio Role.Switch o Role.Button), stateDescription (ad esempio "On", "Off", "Selezionato" o "Non selezionato") ed eventuali etichette di azione pertinenti. Per saperne di più, consulta Componenti personalizzati.
Utilizza indicatori diversi dal colore
Per aiutare gli utenti con daltonismo, utilizza indicatori diversi dal colore per distinguere gli elementi UI nelle schermate della tua app. Queste tecniche possono includere l'utilizzo di forme o dimensioni diverse, la fornitura di testo o pattern visivi o l'aggiunta di feedback audio o tattile (aptico) per evidenziare le differenze degli elementi.
La Figura 1 mostra due versioni di un'attività. Una versione utilizza solo il colore per distinguere tra due possibili azioni in un flusso di lavoro. L'altra versione utilizza la best practice di includere forme e testo oltre al colore per evidenziare le differenze tra le due opzioni:
Rendi i contenuti multimediali più accessibili
Se stai sviluppando un'app che include contenuti multimediali, come un video clip o una registrazione audio, cerca di aiutare gli utenti con diversi tipi di esigenze di accessibilità a comprendere il materiale. In particolare, prova a eseguire le seguenti operazioni:
- Includi controlli che consentano agli utenti di mettere in pausa o interrompere i contenuti multimediali, modificare il volume e attivare/disattivare i sottotitoli (sottotitoli codificati).
- Se un video presenta informazioni essenziali per completare un flusso di lavoro, fornisci gli stessi contenuti in un formato alternativo, ad esempio una trascrizione.
Risorse aggiuntive
Per saperne di più su come rendere la tua app più accessibile, consulta le seguenti risorse aggiuntive: