Le API Material, Compose UI e Foundation implementano e offrono molte pratiche accessibili per impostazione predefinita. Contengono una semantica integrata che segue il loro ruolo e la loro funzione specifici, il che significa che la maggior parte del supporto per l'accessibilità viene fornito con poco o nessun lavoro aggiuntivo.
L'utilizzo delle API appropriate per lo scopo appropriato in genere significa che i componenti sono dotati di comportamenti di accessibilità predefiniti che coprono i casi d'uso standard, ma ricordati di verificare se queste impostazioni predefinite soddisfano le tue esigenze di accessibilità. In caso contrario, Compose offre anche modi per soddisfare requisiti più specifici.
Conoscere la semantica e i pattern di accessibilità predefiniti nelle API Compose aiuta a comprendere come utilizzarle tenendo presente l'accessibilità, nonché a supportare l'accessibilità in componenti più personalizzati.
Dimensioni minime dei touch target
Ogni elemento sullo schermo che è possibile selezionare, toccare o con cui è possibile interagire deve essere abbastanza grande da consentire un'opportuna interazione. Quando imposti le dimensioni di questi elementi, assicurati di impostare la dimensione minima su 48 dp per rispettare correttamente le linee guida sull'accessibilità di Material Design.
I componenti Material, come Checkbox
, RadioButton
, Switch
,
Slider
e Surface
, impostano questa dimensione minima internamente, ma solo
quando il componente può ricevere azioni utente. Ad esempio, quando un Checkbox
ha il parametro onCheckedChange
impostato su un valore non nullo, la casella di controllo include un padding per avere una larghezza e un'altezza di almeno 48 dp.
@Composable private fun CheckableCheckbox() { Checkbox(checked = true, onCheckedChange = {}) }

Quando il parametro onCheckedChange
è impostato su null, il padding non viene incluso perché non è possibile interagire direttamente con il componente.
@Composable private fun NonClickableCheckbox() { Checkbox(checked = true, onCheckedChange = null) }

Quando implementi controlli di selezione come Switch
, RadioButton
o
Checkbox
, in genere trasferisci il comportamento cliccabile a un contenitore principale impostando il callback del clic sul componibile su null
e aggiungendo un
modificatore toggleable
o selectable
al componibile principale.
@Composable private fun CheckableRow() { MaterialTheme { var checked by remember { mutableStateOf(false) } Row( Modifier .toggleable( value = checked, role = Role.Checkbox, onValueChange = { checked = !checked } ) .padding(16.dp) .fillMaxWidth() ) { Text("Option", Modifier.weight(1f)) Checkbox(checked = checked, onCheckedChange = null) } } }

Quando le dimensioni di un componibile selezionabile sono inferiori alle dimensioni minime del touch target, Compose aumenta comunque le dimensioni del touch target. Ciò avviene espandendo le dimensioni del target di tocco al di fuori dei confini del composable.
Il seguente esempio contiene un Box
molto piccolo cliccabile. L'area di destinazione del tocco viene espansa automaticamente oltre i confini del Box
, quindi il tocco accanto al Box
attiva comunque l'evento di clic.
@Composable private fun SmallBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .size(1.dp) ) } }

Per evitare possibili sovrapposizioni tra le aree di tocco di composabili diversi, utilizza sempre una dimensione minima sufficientemente grande per il composable. Nell'esempio, significa utilizzare il modificatore sizeIn
per impostare la dimensione minima della casella interna:
@Composable private fun LargeBox() { var clicked by remember { mutableStateOf(false) } Box( Modifier .size(100.dp) .background(if (clicked) Color.DarkGray else Color.LightGray) ) { Box( Modifier .align(Alignment.Center) .clickable { clicked = !clicked } .background(Color.Black) .sizeIn(minWidth = 48.dp, minHeight = 48.dp) ) } }

Elementi grafici
Quando definisci un composable Image
o Icon
, non esiste un modo automatico per il framework Android di capire cosa viene visualizzato dall'app. Devi passare una descrizione testuale dell'elemento grafico.
Immagina una schermata in cui l'utente può condividere la pagina corrente con gli amici. Questa schermata contiene un'icona di condivisione cliccabile:

Basandosi solo sull'icona, il framework Android non può descriverla a un utente con disabilità visive. Il framework Android ha bisogno di una descrizione testuale aggiuntiva dell'icona.
Il parametro contentDescription
descrive un elemento grafico. Utilizza una stringa localizzata, in quanto visibile all'utente.
@Composable private fun ShareButton(onClick: () -> Unit) { IconButton(onClick = onClick) { Icon( imageVector = Icons.Filled.Share, contentDescription = stringResource(R.string.label_share) ) } }
Alcuni elementi grafici sono puramente decorativi e potresti non volerli comunicare all'utente. Quando imposti il parametro contentDescription
su null
, indichi al framework Android che questo elemento non ha azioni o stato associati.
@Composable private fun PostImage(post: Post, modifier: Modifier = Modifier) { val image = post.imageThumb ?: painterResource(R.drawable.placeholder_1_1) Image( painter = image, // Specify that this image has no semantic meaning contentDescription = null, modifier = modifier .size(40.dp, 40.dp) .clip(MaterialTheme.shapes.small) ) }
contentDescription
è pensato principalmente per essere utilizzato per elementi grafici, come le immagini. I componenti di materiale, come Button
o Text
, e i comportamenti utili, come clickable
o toggleable
, sono dotati di altre semantiche predefinite che descrivono il loro comportamento intrinseco e possono essere modificati tramite altre API Compose.
Elementi interattivi
Le API Material e Foundation Compose creano elementi dell'interfaccia utente con cui gli utenti possono interagire tramite le API dei modificatori clickable
e toggleable
. Poiché
i componenti interattivi possono essere costituiti da più elementi, clickable
e
toggleable
uniscono la semantica dei relativi elementi secondari per impostazione predefinita, in modo che il componente
venga trattato come un'entità logica.
Ad esempio, un materiale Button
potrebbe essere costituito da un'icona secondaria e del testo.
Invece di trattare gli elementi secondari come singoli elementi, un pulsante Material unisce la loro semantica per impostazione predefinita, in modo che i servizi di accessibilità possano raggrupparli di conseguenza:

Analogamente, l'utilizzo del modificatore clickable
fa sì che un composable riunisca anche la semantica dei suoi discendenti in un'unica entità, che viene inviata ai servizi di accessibilità con una rappresentazione dell'azione corrispondente:
Row( // Uses `mergeDescendants = true` under the hood modifier = Modifier.clickable { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open", ) Text("Accessibility in Compose") }
Puoi anche impostare un onClickLabel
specifico sull'elemento principale cliccabile per fornire informazioni aggiuntive ai servizi di accessibilità e offrire una rappresentazione più raffinata dell'azione:
Row( modifier = Modifier .clickable(onClickLabel = "Open this article") { openArticle() } ) { Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Open" ) Text("Accessibility in Compose") }
Utilizzando TalkBack come esempio, questo modificatore clickable
e la relativa etichetta di clic
consentirebbero a TalkBack di fornire un suggerimento di azione "Tocca due volte per aprire questo
articolo", anziché il feedback predefinito più generico "Tocca due volte per attivare".
Questo feedback cambia in base al tipo di azione. Un clic prolungato fornisce un suggerimento di TalkBack "Tocca due volte e tieni premuto per", seguito da un'etichetta:
Row( modifier = Modifier .combinedClickable( onLongClickLabel = "Bookmark this article", onLongClick = { addToBookmarks() }, onClickLabel = "Open this article", onClick = { openArticle() }, ) ) {}
In alcuni casi, potresti non avere accesso diretto al modificatore clickable
(ad esempio, quando è impostato in un livello nidificato inferiore),ma voler comunque cambiare l'etichetta dell'annuncio rispetto al valore predefinito. A questo scopo, separa l'impostazione di clickable
dalla modifica dell'annuncio utilizzando il modificatore semantics
e imposta l'etichetta del clic lì per modificare la rappresentazione dell'azione:
@Composable private fun ArticleList(openArticle: () -> Unit) { NestedArticleListItem( // Clickable is set separately, in a nested layer: onClickAction = openArticle, // Semantics are set here: modifier = Modifier.semantics { onClick( label = "Open this article", action = { // Not needed here: openArticle() true } ) } ) }
In questo caso, non è necessario passare l'azione di clic due volte, poiché le API Compose esistenti, come clickable
o Button
, si occupano di questo aspetto. Questo perché la logica di unione garantisce che l'etichetta e l'azione del modificatore più esterno vengano prese in considerazione per le informazioni presenti.
Nell'esempio precedente, l'azione di clic openArticle()
viene passata in profondità da NestedArticleListItem
automaticamente alla sua semantica clickable
e può essere lasciata nulla nella seconda azione di modifica della semantica. Tuttavia, l'etichetta dei clic viene presa dal secondo modificatore di semanticaonClick(label = "Open this article")
, in quanto non era presente nel primo.
Potresti riscontrare scenari in cui ti aspetti che la semantica secondaria venga unita a quella principale, ma ciò non accade. Per informazioni più dettagliate, consulta la sezione Unione ed eliminazione.
Componenti personalizzati
Come regola generale, per i componenti personalizzati, esamina l'implementazione di un componente simile nella libreria Material o in altre librerie Compose e imita o modifica il relativo comportamento di accessibilità, se opportuno.
Ad esempio, se stai sostituendo il componente Material Checkbox
con la tua implementazione, esaminare l'implementazione esistente della casella di controllo ti ricorderà di aggiungere il modificatore triStateToggleable
, che gestisce le proprietà di accessibilità per questo componente.
Inoltre, utilizza ampiamente i modificatori di Foundation, in quanto includono considerazioni sull'accessibilità e pratiche di composizione esistenti trattate in questa sezione.
Puoi anche trovare un esempio di componente di pulsante di attivazione/disattivazione personalizzato nella sezione Semantika di impostazione e eliminazione, nonché informazioni più dettagliate su come supportare l'accessibilità nei componenti personalizzati nelle linee guida per le API.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Accessibilità in Componi
- [Material Design 2 in Compose][19]
- Testare il layout di Componi