Per aiutare gli utenti con esigenze di accessibilità, il framework Android ti consente di creare un servizio di accessibilità che possa presentare i contenuti delle app agli utenti e anche utilizzare le app per loro conto.
Android fornisce 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 ai gesti dell'utente.
- Switch Access: aiuta le persone con disabilità motorie. Mette in evidenza 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, quest'ultima deve seguire le best practice descritte in questa pagina, che si basano sulle linee guida descritte in Rendere le app più accessibili.
Ognuna di queste best practice, descritte nelle sezioni seguenti, può migliorare ulteriormente l'accessibilità della tua app:
- Elementi dell'etichetta
- Gli utenti devono essere in grado di comprendere i contenuti e lo scopo di ogni elemento UI interattivo e significativo all'interno dell'app.
- Aggiungere azioni di accessibilità
- Se aggiungi azioni di accessibilità, puoi consentire agli utenti dei servizi di accessibilità di completare i flussi utente critici all'interno della tua app.
- Utilizzare 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 poco o nessun lavoro aggiuntivo. Compose offre anche modi per supportare requisiti di accessibilità più specifici non coperti dalle funzionalità predefinite.
- Utilizzare segnali diversi dal colore
- Gli utenti devono essere in grado di distinguere chiaramente le categorie di elementi in un'interfaccia utente. A tal fine, utilizza motivi e posizione, oltre al colore, per esprimere queste differenze.
- Rendere i contenuti multimediali più accessibili
- Aggiungi descrizioni ai contenuti video o audio della tua app in modo che gli utenti che consumano questi contenuti non debbano fare affidamento esclusivamente su segnali visivi o uditivi.
Elementi delle etichette
È importante fornire agli utenti etichette utili e descrittive per ogni elemento UI interattivo nella 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
hanno un supporto dell'accessibilità predefinito. Tuttavia, se devi specificare manualmente le proprietà semantiche di un elemento dell'interfaccia utente, 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 etichetti 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 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 cosa devono inserire gli utenti come input.
Nel seguente esempio, TextField ha un parametro label che fornisce
una descrizione dell'accessibilità.
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
Per saperne di più su testo e input dell'utente, consulta Configurare 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 a un solo elemento sullo schermo quando annunciano un'etichetta. Questa corrispondenza consente agli utenti di sapere quando scorrono l'interfaccia utente 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 nel
seguente snippet:
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 saperne di più sulle proprietà semantiche per elenchi e griglie, consulta Informazioni su elenchi e elementi.
Gruppi di contenuti correlati
Se la tua app mostra diversi elementi dell'interfaccia utente che formano un gruppo naturale, ad esempio
i dettagli di un brano o gli attributi di un messaggio, disponi questi elementi 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 di tecnologie per la disabilità a scoprire le informazioni sullo schermo in modo più efficiente.
Nel seguente snippet, il composable Row funge da contenitore principale.
All'interno di Row sono presenti elementi correlati che mostrano i metadati di un post del blog: l'avatar dell'autore, il nome dell'autore e il tempo di lettura stimato.
L'impostazione 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, trasmettendo comunque il significato dell'elemento.
Nota:in generale, quando crei una descrizione dei contenuti per un gruppo, evita di aggregare il testo dei relativi gruppi 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 ulteriori informazioni sull'unione della semantica, consulta Unione e cancellazione.
Intestazioni all'interno del testo
Alcune app utilizzano i titoli 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 i titoli 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 saperne di più sulla proprietà semantica paneTitle, consulta
Componenti simili a finestre.
Elementi decorativi
Se un elemento della tua UI esiste solo a scopo di spaziatura o aspetto visivo, imposta le proprietà appropriate sull'elemento per indicare che i servizi di accessibilità possono ignorarlo.
Per i composable 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 componente 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 cancellarne la 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, vedi Cancellare e impostare la semantica.
Aggiungere 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 tuo elemento componibile personalizzato modifica lo stato dell'app in 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 con i tocco standard, utilizza customActions.
Ad esempio, se la tua app consente agli utenti di trascinare un elemento in un'altra posizione o di scorrere su un elemento di 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 sarebbero 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 chiuderlo, 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 delle azioni.
Per ulteriori informazioni sulle azioni personalizzate, vedi Azioni personalizzate.
Rendere comprensibili le azioni disponibili
Quando un elemento dell'interfaccia utente supporta azioni come tocco e pressione, un servizio di accessibilità come TalkBack lo annuncia come "Tocca due volte e tieni premuto per la pressione prolungata".
Questo annuncio generico non fornisce all'utente alcun contesto su cosa fa un'azione di tocco prolungato.
Per rendere più utile questo annuncio, specifica una descrizione significativa per l'azione.
In Scrivi, 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 nel seguente esempio:
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.
Utilizzare le funzioni di accessibilità integrate
Quando progetti l'interfaccia utente della tua app, sfrutta le funzionalità di accessibilità integrate per evitare di implementare nuovamente funzionalità già esistenti. Le API Material, Compose UI e Foundation implementano e offrono molte pratiche accessibili per impostazione predefinita.
In Jetpack Compose, utilizza i composable integrati come Button, Switch e
Checkbox per creare UI accessibili. Questi componenti sono preconfigurati con
modificatori semantics, come role e stateDescription, che puoi utilizzare
per rendere le tue app più accessibili.
Applicare la semantica ai componenti personalizzati
Quando crei un componente personalizzato, tieni presente il tipo di supporto per l'accessibilità
necessario per svolgere il suo ruolo. Spesso, le API Compose standard che già utilizzi, come clickable, toggleable o
selectable, sono sufficienti perché compilano automaticamente l'albero semantico.
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 Indeterminate).
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 devi 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") e qualsiasi etichetta di azione pertinente. Per saperne di più, consulta Componenti personalizzati.
Utilizzare segnali diversi dal colore
Per aiutare gli utenti con daltonismo, utilizza segnali diversi dal colore per distinguere gli elementi della UI all'interno delle schermate della tua app. Queste tecniche possono includere l'utilizzo di forme o dimensioni diverse, la fornitura di pattern di testo o visivi o l'aggiunta di feedback basati su audio o tocco (aptico) per contrassegnare le differenze tra gli 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:
Rendere più accessibili i contenuti multimediali
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 svolgere le seguenti operazioni:
- Includi controlli che consentano agli utenti di mettere in pausa o interrompere la riproduzione dei contenuti multimediali, modificare il volume e attivare/disattivare i 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: