À medida que os serviços de acessibilidade navegam pelos elementos na tela, é importante que esses elementos sejam agrupados, separados ou até mesmo ocultos na granularidade correta. Quando cada elemento combinável de baixo nível na tela é destacado de forma independente, os usuários precisam interagir muito para navegar pela tela. Se os elementos forem combinados de forma exagerada, os usuários podem não compreender quais elementos estão agrupados. Se houver elementos na tela que sejam puramente decorativos, eles poderão ser ocultados dos serviços de acessibilidade. Nesses casos, é possível usar as APIs do Compose para mesclar, limpar e ocultar a semântica.
Semântica de mesclagem
Quando você aplica um modificador clickable
a um elemento combinável pai, o Compose
mescla automaticamente todos os elementos filhos abaixo dele. Para entender como
os componentes interativos do Compose Material e do Foundation usam estratégias de mesclagem
por padrão, consulte a seção Elementos interativos.
É comum que um componente consista em vários elementos combináveis. Esses combináveis podem formar um grupo lógico e cada um pode conter informações importantes, mas talvez você ainda queira que os serviços de acessibilidade os considerem como um único elemento.
Por exemplo, imagine um elemento combinável que mostre o avatar de um usuário, o nome e algumas informações extras:

Você pode ativar o Compose para mesclar esses elementos usando o parâmetro mergeDescendants
no modificador de semântica. Dessa forma, os serviços de acessibilidade tratam o
componente como uma entidade, e todas as propriedades semânticas dos descendentes são
mescladas:
@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") } } }
Os serviços de acessibilidade agora se concentram no contêiner todo de uma vez e mesclam o conteúdo dele:

Cada propriedade semântica tem uma estratégia de mesclagem definida. Por exemplo, a
propriedade ContentDescription
adiciona todos os valores descendentes de ContentDescription
a uma lista. É possível verificar a estratégia de mesclagem de uma propriedade semântica
verificando a implementação da mergePolicy
em SemanticsProperties.kt.
As propriedades podem assumir o valor pai ou filho, mesclar os valores em uma lista
ou string, não permitir a mesclagem de nenhum tipo e gerar uma exceção ou qualquer
outra estratégia de mesclagem personalizada.
Há outros cenários em que você espera que a semântica das crianças seja mesclada a
uma mãe, mas isso não acontece. No exemplo abaixo, temos
clickable
item de lista pai com elementos filhos, e podemos esperar que o
elemento pai os mescle:

@Composable private fun ArticleListItem( openArticle: () -> Unit, addToBookmarks: () -> Unit, ) { Row(modifier = Modifier.clickable { openArticle() }) { // Merges with parent clickable: Icon( painter = painterResource(R.drawable.ic_logo), contentDescription = "Article thumbnail" ) ArticleDetails() // Defies the merge due to its own clickable: BookmarkButton(onClick = addToBookmarks) } }
Quando o usuário pressiona o item clickable
Row
, o artigo é aberto. Aninhado
dentro, há um BookmarkButton
para adicionar o artigo aos favoritos. Esse botão aninhado
aparece como não mesclado, enquanto o restante do conteúdo filho dentro da linha é
mesclado:

Row
. A árvore não mesclada contém nós separados para cada elemento combinável Text
.Por design, alguns elementos combináveis não são mesclados automaticamente em um elemento pai. Um
elemento pai não pode mesclar os filhos quando eles também estão sendo mesclados, definindo mergeDescendants = true
explicitamente ou sendo componentes que
se mesclam, como botões ou elementos clicáveis. Saber como algumas APIs mesclam ou
desafios de mesclagem pode ajudar você a depurar alguns comportamentos potencialmente inesperados.
Use a mesclagem quando os elementos filhos formam um grupo lógico e sensato
sob o elemento pai. No entanto, se os filhos aninhados precisarem ajustar ou remover manualmente
as próprias semânticas, outras APIs podem ser mais adequadas às suas necessidades (por exemplo,
clearAndSetSemantics
).
Limpar e definir semântica
Se as informações semânticas precisarem ser completamente apagadas ou substituídas, uma
API poderosa para usar é clearAndSetSemantics
.
Quando um componente precisa limpar a semântica própria e a semântica dos descendentes, use essa API com uma lambda vazia. Quando a semântica precisar ser substituída, inclua o novo conteúdo dentro do lambda.
Ao limpar com um lambda vazio, as semânticas limpas não são
enviadas a nenhum consumidor que use essas informações, como acessibilidade, preenchimento automático
ou testes. Ao substituir o conteúdo com
clearAndSetSemantics{/*semantic information*/}
, as novas semânticas substituem todas
as semânticas anteriores do elemento e dos descendentes.
Confira a seguir um exemplo de componente de alternância personalizado, representado por uma linha interativa com um ícone e um texto:
// 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?") } }
Embora o ícone e o texto tenham algumas informações semânticas, juntos eles não indicam que esse componente é um botão de alternância. A mesclagem não é suficiente porque é necessário fornecer mais informações sobre o componente.
Como o snippet acima cria um componente de alternância personalizado, é necessário adicionar
a capacidade de alternância, bem como a semântica stateDescription
,
toggleableState
e role
. Dessa forma, o status
do componente e a ação associada ficam disponíveis. Por exemplo, o TalkBack anuncia
"Toque duas vezes para alternar" em vez de "Toque duas vezes para ativar".
Ao limpar a semântica original e definir novas semânticas mais descritivas, os serviços de acessibilidade agora podem identificar que este é um componente comutável que pode alternar o estado.
Ao usar clearAndSetSemantics
, considere o seguinte:
- Como os serviços não recebem informações quando essa API está definida, é melhor
usá-la com moderação.
- As informações semânticas podem ser usadas por agentes de IA e serviços semelhantes para entender a tela. Portanto, elas só devem ser limpas quando necessário.
- A semântica personalizada pode ser definida na API lambda.
- A ordem dos modificadores é importante. Essa API limpa toda a semântica que é aplicada depois dela, independentemente de outras estratégias de mesclagem.
Ocultar semântica
Em alguns cenários, os elementos não precisam ser enviados aos serviços de
acessibilidade. Talvez as informações adicionais sejam redundantes para acessibilidade
ou sejam puramente decorativas e não interativas. Nesses casos, é possível
ocultar elementos com a API hideFromAccessibility
.
Nos exemplos a seguir, há componentes que podem precisar ser ocultos: uma marca d'água redundante que abrange um componente e um caractere usado para separar informações de forma decorativa.
@Composable fun WatermarkExample( watermarkText: String, content: @Composable () -> Unit, ) { Box { WatermarkedContent() // Mark the watermark as hidden to accessibility services. WatermarkText( text = watermarkText, color = Color.Gray.copy(alpha = 0.5f), modifier = Modifier .align(Alignment.BottomEnd) .semantics { hideFromAccessibility() } ) } } @Composable fun DecorativeExample() { Text( modifier = Modifier.semantics { hideFromAccessibility() }, text = "A dot character that is used to decoratively separate information, like •" ) }
O uso de hideFromAccessibility
garante que a marca d'água e a decoração sejam
ocultas dos serviços de acessibilidade, mas ainda mantenham a semântica para outros
casos de uso, como testes.
Detalhes dos casos de uso
Confira a seguir um resumo de casos de uso para entender como diferenciar claramente as APIs anteriores:
- Quando o conteúdo não é destinado a ser usado por serviços de acessibilidade:
- Use
hideFromAccessibility
quando o conteúdo for possivelmente decorativo ou redundante, mas ainda precisar ser testado. - Use
clearAndSetSemantics{}
com uma lambda vazia quando a semântica de pais e filhos precisar ser limpa para todos os serviços. - Use
clearAndSetSemantics{/*content*/}
com conteúdo dentro da lambda quando a semântica de um componente precisar ser definida manualmente.
- Use
- Quando o conteúdo precisa ser tratado como uma entidade e precisa que todas as informações dos filhos sejam completas:
- Use descendentes semânticos de mesclagem.

Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Acessibilidade no Compose
- [Material Design 2 no Compose][19]
- Como testar o layout do Compose