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. Ciò significa che la maggior parte del supporto per l'accessibilità viene fornita con poco o nessun lavoro aggiuntivo.
L'utilizzo delle API appropriate per lo scopo appropriato significa che i componenti di solito sono dotati di comportamenti di accessibilità predefiniti che coprono i casi d'uso standard. Tuttavia, verifica sempre se queste impostazioni predefinite soddisfano le tue esigenze di accessibilità. In caso contrario, Compose offre modi per soddisfare requisiti più specifici.
Comprendere la semantica e i pattern di accessibilità predefiniti nelle API Compose ti aiuta a utilizzarli tenendo presente l'accessibilità. Inoltre, ti aiuta 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 ridimensioni questi elementi, assicurati di impostare la dimensione minima su 48 dp per seguire correttamente le linee guida sull'accessibilità di Material Design.
I componenti Material, come Checkbox, RadioButton, Switch,
Slider e Surface, impostano internamente questa dimensione minima, ma solo
quando il componente può ricevere azioni dell'utente. Ad esempio, quando un Checkbox ha
il parametro onCheckedChange impostato su un valore non nullo, la casella di controllo include
un riempimento 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
è 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 sposti il comportamento cliccabile in un contenitore principale
impostando il callback di clic sull'elemento componibile su null e aggiungendo un
modificatore toggleable o selectable all'elemento 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 cliccabile sono inferiori a quelle minime del touch target, Compose aumenta comunque le dimensioni del touch target. Aumenta le dimensioni del target di tocco al di fuori dei limiti del componente componibile.
L'esempio seguente contiene un Box molto piccolo su cui è possibile fare clic. L'area di destinazione
tattile viene espansa automaticamente oltre i limiti di Box, quindi toccare
accanto a 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 composable diversi, utilizza sempre
una dimensione minima sufficientemente grande per il composable. Nell'esempio, ciò
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 elemento componibile Image o Icon, non esiste un modo automatico per il framework Android di comprendere cosa sta visualizzando l'app. Devi superare 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:
In base alla sola icona, il framework Android non può descriverla a un utente con disabilità visiva. Il framework Android richiede 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 stati 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 è destinato principalmente all'uso per elementi grafici,
come le immagini. I componenti Material, come Button o Text, e i comportamenti
azionabili, come clickable o toggleable, sono dotati di altre semantiche
predefinite che descrivono il loro comportamento intrinseco e possono essere modificate 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 potrebbero 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'unica entità logica.
Ad esempio, un Material Button potrebbe essere costituito da un'icona secondaria e da un po' di testo. Anziché trattare i bambini come singoli individui, un Material
Button unisce la semantica dei figli per impostazione predefinita, in modo che i servizi
di accessibilità possano raggrupparli di conseguenza:
Allo stesso modo, l'utilizzo del modificatore clickable fa sì che un elemento componibile
unisca 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 sul genitore 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
consentono a TalkBack di fornire un suggerimento per l'azione "Tocca due volte per aprire questo
articolo", anziché il feedback predefinito più generico "Tocca due volte per
attivare".
Questo feedback cambia a seconda del tipo di azione. Un clic lungo fornirebbe 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 vuoi comunque modificare l'etichetta dell'annuncio rispetto a quella predefinita. A questo scopo, separa l'impostazione di
clickable dalla modifica dell'annuncio utilizzando il modificatore semantics
e impostando l'etichetta del clic in modo da 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 } ) } ) }
Non è necessario superare l'azione di clic due volte. Le API Compose esistenti, come
clickable o Button, gestiscono questa operazione per te. La logica di unione verifica
che l'etichetta e l'azione del modificatore più esterno vengano eseguite per le informazioni
presenti. Nell'esempio precedente, NestedArticleListItem passa automaticamente
l'azione di clic openArticle() alla semantica clickable. Puoi
lasciare l'azione di clic null nella seconda azione del modificatore semantico. Tuttavia,
l'etichetta del clic viene presa dal secondo modificatore semantico
onClick(label = "Open this document") perché non era presente nel primo.
Potresti riscontrare scenari in cui ti aspetti che la semantica dei contenuti secondari venga unita a quella dei contenuti principali, ma ciò non accade. Per informazioni più dettagliate, consulta Unione e cancellazione.
Componenti personalizzati
Quando crei un componente personalizzato, esamina l'implementazione di un componente simile nella libreria Material o in altre librerie Compose. Poi,
imita o modifica il suo comportamento di accessibilità in modo appropriato. Ad esempio, se
sostituisci il Material Checkbox con la tua implementazione, esaminando
l'implementazione Checkbox esistente ti verrà ricordato di aggiungere il
modificatore triStateToggleable, che
gestisce le proprietà di
accessibilità del componente. Inoltre, utilizza molto i modificatori di Foundation, in quanto includono considerazioni sull'accessibilità integrate e pratiche di Compose esistenti trattate in questa sezione.
Puoi anche trovare un esempio di componente di attivazione/disattivazione personalizzato nella sezione Semantica chiara e impostata, 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 Scrivi
- Testare il layout di Composizione