Oltre alle informazioni principali che un composable contiene, come una stringa di testo
di un composable Text
, può essere utile avere altre informazioni complementari
sui componenti dell'interfaccia utente.
Le informazioni sul significato e sul ruolo di un componente in Compose si chiamano semantica e sono un modo per fornire contesto aggiuntivo sui componenti a servizi come accessibilità, compilazione automatica e test. Ad esempio, un'icona della fotocamera potrebbe essere visivamente solo un'immagine, ma il significato semantico potrebbe essere "Scatta una foto".
Combinando la semantica appropriata con le API Compose appropriate, fornisci ai servizi di accessibilità quante più informazioni possibili sul tuo componente, che poi decide come rappresentarlo all'utente.
Le API Material e Compose UI e Foundation sono dotate di una semantica integrata che segue il loro ruolo e la loro funzione specifici, ma puoi anche modificare questa semantica per le API esistenti o impostarne di nuove per i componenti personalizzati, in base ai tuoi requisiti specifici.
Proprietà semantiche
Le proprietà semantiche trasmettono il significato del composable corrispondente. Ad esempio, il composable Text
contiene una proprietà semantica text
, perché è il significato del composable. Un Icon
contiene una proprietà contentDescription
(se impostata dallo sviluppatore) che indica in testo il significato dell'icona.
Considera in che modo le proprietà di semantica trasmettono il significato di un composable. Prendi in considerazione un
Switch
. Ecco come appare all'utente:

Switch
negli stati "On" e "Off".Per descrivere il significato di questo elemento, puoi dire quanto segue: "Questo è un pulsante di attivazione/disattivazione, ovvero un elemento attivabile/disattivabile nel suo stato "On". Puoi fare clic su di essa per interagire."
È esattamente a questo scopo che vengono utilizzate le proprietà di semantica. Il nodo semantico di questo elemento Switch contiene le seguenti proprietà, visualizzate con l'ispettore di layout:

Switch
componibileRole
indica il tipo di elemento. StateDescription
descrive come deve essere fatto riferimento allo stato "On". Per impostazione predefinita, si tratta di una versione localizzata della parola "On", ma può essere resa più specifica (ad esempio "Attivata") in base al contesto. ToggleableState
indica lo stato attuale dello switch. La proprietà
OnClick
fa riferimento al metodo utilizzato per interagire con questo elemento.
Monitorare le proprietà semantiche di ogni composable nella tua app sblocca moltissime funzionalità efficaci:
- I servizi di accessibilità utilizzano le proprietà per rappresentare l'interfaccia utente visualizzata sullo schermo e consentire agli utenti di interagire con essa. Per il componente composable Pulsante, TalkBack potrebbe annunciare: "On; Pulsante; tocca due volte per attivare/disattivare". L'utente può toccare due volte lo schermo per disattivare l'opzione.
-
Il framework di test utilizza le proprietà per trovare i nodi, interagire con essi e fare affermazioni:
val mySwitch = SemanticsMatcher.expectValue( SemanticsProperties.Role, Role.Switch ) composeTestRule.onNode(mySwitch) .performClick() .assertIsOff()
I composabili e i modificatori basati sulla libreria di base di Compose impostano già per impostazione predefinita le proprietà pertinenti. Se vuoi, puoi modificare manualmente queste proprietà per migliorare il supporto dell'accessibilità per casi d'uso specifici o modificare la strategia di unione o eliminazione dei composabili.
Per segnalare ai servizi di accessibilità il tipo specifico di contenuti del componente, puoi applicare una serie di semantiche diverse. Queste aggiunte supporteranno le informazioni semantiche principali esistenti e aiuteranno i servizi di accessibilità a perfezionare il modo in cui il componente viene rappresentato, annunciato o con cui viene interagito.
Per un elenco completo delle proprietà di semantica, consulta l'oggetto
SemanticsProperties
. Per un elenco completo delle possibili azioni di accessibilità, consulta l'oggetto SemanticsActions
.
Intestazioni
Le app spesso contengono schermate con contenuti ricchi di testo, come articoli lunghi o pagine di notizie, che in genere sono suddivise in diverse sezioni con intestazioni:

Gli utenti con esigenze di accessibilità possono avere difficoltà a navigare facilmente in una schermata di questo tipo. Per migliorare l'esperienza di navigazione, alcuni servizi di accessibilità consentono di navigare più facilmente tra sezioni o intestazioni. Per attivare questa opzione,
indica che il componente è un heading
definendone la proprietà
semantica:
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
Avvisi e popup
Se il componente è un avviso o un popup, ad esempio Snackbar
, ti consigliamo di indicare ai servizi di accessibilità che è possibile comunicare agli utenti una nuova struttura o aggiornamenti dei contenuti.
I componenti simili agli avvisi possono essere contrassegnati con la proprietà di semantica liveRegion
. In questo modo, i servizi di accessibilità possono notificare automaticamente all'utente le modifiche a questo componente o ai suoi componenti secondari:
PopupAlert( message = "You have a new message", modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite } )
Devi utilizzare liveRegionMode.Polite
nella maggior parte dei casi in cui l'attenzione degli utenti deve essere attirata solo brevemente su avvisi o contenuti importanti in mutazione sullo schermo.
Ti consigliamo di utilizzare liveRegion.Assertive
con parsimonia per evitare feedback che potrebbero causare interruzioni.
Deve essere utilizzato in situazioni in cui è fondamentale informare gli utenti di contenuti urgenti:
PopupAlert( message = "Emergency alert incoming", modifier = Modifier.semantics { liveRegion = LiveRegionMode.Assertive } )
Le regioni in tempo reale non devono essere utilizzate per i contenuti che si aggiornano di frequente, come i timer di conto alla rovescia, per evitare di sovraccaricare gli utenti con feedback costanti.
Componenti simili a finestre
I componenti personalizzati simili a finestre, come ModalBottomSheet
, richiedono indicatori aggiuntivi per distinguerli dai contenuti circostanti. A questo scopo, puoi utilizzare la semantica paneTitle
, in modo che eventuali modifiche pertinenti a finestre o riquadri possano essere rappresentate in modo appropriato dai servizi di accessibilità, insieme alle relative informazioni semantiche principali:
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
Come riferimento, consulta come Material 3 utilizza paneTitle
per i suoi componenti.
Componenti di errore
Per altri tipi di contenuti, come i componenti simili a errori, ti consigliamo di approfondire le informazioni semantiche principali per gli utenti con esigenze di accessibilità.
Quando definisci gli stati di errore, puoi comunicare ai servizi di accessibilità la semantica di error
e fornire messaggi di errore espansi.
In questo esempio, TalkBack legge le informazioni del testo dell'errore principale, seguite da messaggi aggiuntivi espansi:
Error( errorText = "Fields cannot be empty", modifier = Modifier .semantics { error("Please add both email and password") } )
Componenti di monitoraggio dell'avanzamento
Per i componenti personalizzati che monitorano l'avanzamento, ti consigliamo di informare gli utenti delle modifiche apportate, incluso il valore corrente dell'avanzamento, l'intervallo e la dimensione del passo. Puoi farlo con la semantica progressBarRangeInfo
: in questo modo, i servizi di accessibilità sono a conoscenza delle modifiche dell'avanzamento e possono aggiornare gli utenti di conseguenza. Inoltre, le diverse tecnologie per la disabilità potrebbero avere modi unici per suggerire l'aumento e la diminuzione della progressione.
ProgressInfoBar( modifier = Modifier .semantics { progressBarRangeInfo = ProgressBarRangeInfo( current = progress, range = 0F..1F ) } )
Informazioni su elenchi e articoli
In elenchi e griglie personalizzate con molti elementi, potrebbe essere utile per i servizi di accessibilità ricevere anche informazioni più dettagliate, come il numero totale di elementi e indici.
Utilizzando le semantiche collectionInfo
e collectionItemInfo
rispettivamente per l'elenco e gli elementi, in questo lungo elenco, i servizi di accessibilità possono informare gli utenti dell'indice dell'elemento in cui si trovano rispetto alla raccolta totale, oltre alle informazioni semantiche testuali:
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) } ) } }
Descrizione dello stato
Un componibile può definire un stateDescription
per la semantica che il framework Android utilizza per leggere lo stato del componibile. Ad esempio, un composable attivabile/disattivabile può trovarsi in uno stato "selezionato" o "deselezionato". In alcuni casi, potresti voler sostituire le etichette di descrizione dello stato predefinite utilizzate da Compose. Puoi farlo specificando esplicitamente le etichette di descrizione dello stato prima di definire un composable come attivabile/disattivabile:
@Composable private fun TopicItem(itemTitle: String, selected: Boolean, onToggle: () -> Unit) { val stateSubscribed = stringResource(R.string.subscribed) val stateNotSubscribed = stringResource(R.string.not_subscribed) Row( modifier = Modifier .semantics { // Set any explicit semantic properties stateDescription = if (selected) stateSubscribed else stateNotSubscribed } .toggleable( value = selected, onValueChange = { onToggle() } ) ) { /* ... */ } }
Azioni personalizzate
Le azioni personalizzate possono essere utilizzate per gesti del touchscreen più complessi, come scorrimento per ignorare o trascinamento, poiché possono essere difficili da usare per gli utenti con disabilità motorie o altre disabilità.
Per rendere più accessibile il gesto di scorrimento per chiudere, puoi collegarlo a un'azione personalizzata, passando l'azione di chiusura e l'etichetta:
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() }
Un servizio di accessibilità come TalkBack evidenzia il componente e suggerisce che sono disponibili altre azioni nel relativo menu, rappresentando l'azione di scorrimento per chiudere:

Un altro caso d'uso per le azioni personalizzate sono gli elenchi lunghi con elementi che hanno più azioni disponibili, poiché potrebbe essere noioso per gli utenti eseguire l'iterazione di ogni azione per ogni singolo elemento:

Per migliorare l'esperienza di navigazione, che è particolarmente utile per le tecnologie per la disabilità basate sulle interazioni come Switch Access o Voice Access, puoi utilizzare azioni personalizzate sul contenitore per spostare le azioni dal singolo traversale in un menu di azioni separato:
ArticleListItemRow( modifier = Modifier .semantics { customActions = listOf( CustomAccessibilityAction( label = "Open article", action = { openArticle() true } ), CustomAccessibilityAction( label = "Add to bookmarks", action = { addToBookmarks() true } ), ) } ) { Article( modifier = Modifier.clearAndSetSemantics { }, onClick = openArticle, ) BookmarkButton( modifier = Modifier.clearAndSetSemantics { }, onClick = addToBookmarks, ) }
In questi casi, assicurati di cancellare manualmente la semantica dei componenti secondari originali con il modificatore clearAndSetSemantics
, poiché li stai spostando nelle azioni personalizzate.
Utilizzando Switch Access come esempio, il relativo menu si apre quando selezioni il contenitore e elenca le azioni nidificate disponibili:


Albero della semantica
Una composizione descrive l'interfaccia utente dell'app e viene prodotta dall'esecuzione di composable. La composizione è una struttura ad albero costituita dai composabili che descrivono l'interfaccia utente.
Accanto alla composizione esiste un albero parallelo, chiamato albero semantico. Questa struttura ad albero descrive l'interfaccia utente in un modo alternativo, comprensibile per i servizi di accessibilità e per il framework di test. I servizi di accessibilità utilizzano la struttura ad albero per descrivere l'app agli utenti con un bisogno specifico. Il framework di test utilizza la struttura ad albero per interagire con la tua app e fare affermazioni in merito. L'albero della semantica non contiene informazioni su come disegnare i composabili, ma contiene informazioni sul significato semantico dei composabili.

Se la tua app è composta da composabili e modificatori della base di Compose e della libreria di Material, l'albero della semantica viene compilato e generato automaticamente. Tuttavia, quando aggiungi composabili di basso livello personalizzati, devi fornire manualmente la relativa semantica. Potrebbero anche esserci situazioni in cui l'albero non rappresenta correttamente o completamente il significato degli elementi sullo schermo. In questo caso, puoi adattarlo.
Prendi ad esempio questo composable del calendario personalizzato:

In questo esempio, l'intero calendario è implementato come un singolo composable di basso livello, utilizzando il composable Layout
e disegnando direttamente in Canvas
.
Se non esegui altre operazioni, i servizi di accessibilità non riceveranno informazioni sufficienti sui contenuti del composable e sulla selezione dell'utente all'interno del calendario. Ad esempio, se un utente fa clic sul giorno contenente il 17, il framework di accessibilità riceve solo le informazioni sulla descrizione dell'intero controllo del calendario. In questo caso, il servizio di accessibilità TalkBack annuncierebbe "Calendario" o, solo leggermente meglio, "Calendario di aprile" e l'utente non saprebbe quale giorno è stato selezionato. Per rendere questo composable più accessibile, dovrai aggiungere manualmente le informazioni semantiche.
Albero unito e non unito
Come accennato in precedenza, ogni composable nella struttura ad albero dell'interfaccia utente potrebbe avere zero o più proprietà semantiche impostate. Quando un composable non ha proprietà di semantica impostate, non è incluso nell'albero della semantica. In questo modo, l'albero della semantica contiene solo i nodi che contengono effettivamente un significato semantico. Tuttavia, a volte per trasmettere il significato corretto di ciò che viene mostrato sullo schermo, è utile anche unire determinati sotto alberi di nodi e trattarli come uno solo. In questo modo, puoi ragionare su un insieme di nodi nel loro complesso, anziché gestire singolarmente ogni nodo discendente. Come regola generale, ogni nodo di questa struttura rappresenta un elemento che può essere attivato quando si utilizzano i servizi di accessibilità.
Un esempio di questo tipo di composable è Button
. Puoi considerare un pulsante come un singolo elemento, anche se può contenere più nodi secondari:
Button(onClick = { /*TODO*/ }) { Icon( imageVector = Icons.Filled.Favorite, contentDescription = null ) Spacer(Modifier.size(ButtonDefaults.IconSpacing)) Text("Like") }
Nell'albero della semantica, le proprietà dei discendenti del pulsante vengono unite e il pulsante viene visualizzato come un singolo nodo foglia nell'albero:

I composabili e i modificatori possono indicare che vogliono unire le proprietà di semantica dei loro discendenti chiamando Modifier.semantics
(mergeDescendants = true) {}
. L'impostazione di questa proprietà su true
indica che
le proprietà di semantica devono essere unite. Nell'esempio Button
, il composable Button
utilizza internamente il modificatore clickable
che include questo
modificatore semantics
. Pertanto, i nodi discendenti del pulsante vengono uniti.
Leggi la documentazione sull'accessibilità per scoprire di più su quando devi modificare il comportamento di unione nel tuo composable.
Diversi modificatori e composabili nelle librerie Foundation e Material Compose hanno questa proprietà impostata. Ad esempio, i modificatori clickable
e toggleable
uniscono automaticamente i relativi discendenti. Inoltre, il componibile ListItem
riunirà i suoi discendenti.
Controlla l'albero
L'albero della semantica è in realtà costituito da due alberi diversi. Esiste un albero di semantica unito, che unisce i nodi discendenti quando mergeDescendants
è impostato su true
.
Esiste anche un albero della semantica non unito, che non applica l'unione, ma mantiene invariati tutti i nodi. I servizi di accessibilità utilizzano l'albero non unito e applicano i propri algoritmi di unione, tenendo conto della proprietà mergeDescendants
. Il framework di test utilizza l'albero unito per impostazione predefinita.
Puoi ispezionare entrambi gli alberi con il metodo printToLog()
. Per impostazione predefinita, come negli esempi precedenti, la registrazione del albero unito viene eseguita. Per stampare invece l'albero non unito, imposta il parametro useUnmergedTree
dell'operatore di corrispondenza onRoot()
su true
:
composeTestRule.onRoot(useUnmergedTree = true).printToLog("MY TAG")
L'ispettore layout ti consente di visualizzare sia l'albero della semantica unito sia quello non unito, selezionando quello preferito nel filtro della visualizzazione:

Per ogni nodo dell'albero, l'ispettore del layout mostra sia le semantiche unite sia le semantiche impostate su quel nodo nel riquadro delle proprietà:

Per impostazione predefinita, i corrispondenti nel framework di test utilizzano l'albero della semantica unito.
Ecco perché puoi interagire con un Button
abbinando il testo visualizzato al suo interno:
composeTestRule.onNodeWithText("Like").performClick()
Per eseguire l'override di questo comportamento, imposta il parametro useUnmergedTree
dei matcher su true
, come per il matcher onRoot
.
Adatta l'albero
Come accennato in precedenza, puoi ignorare o cancellare determinate proprietà di semantica o modificare il comportamento di unione dell'albero. Questo è particolarmente importante quando crei i tuoi componenti personalizzati. Se non imposti le proprietà e il comportamento di unione corretti, la tua app potrebbe non essere accessibile e i test potrebbero comportarsi in modo diverso da quanto previsto. Per scoprire di più sui test, consulta la guida ai test.
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Accessibilità in Componi
- Material Design 2 in Scrivi
- Testare il layout di Componi