Para ajudar usuários com necessidades de acessibilidade, o framework do Android permite criar um serviço de acessibilidade que pode apresentar conteúdo de apps para usuários e também operar apps em nome deles.
O Android fornece vários serviços de acessibilidade do sistema, incluindo:
- TalkBack: ajuda pessoas com baixa visão ou cegas. Ele anuncia o conteúdo por meio de uma voz sintetizada e realiza ações em um app em resposta a gestos do usuário.
- Acesso com interruptor: ajuda pessoas com deficiências motoras. Ele destaca elementos interativos e realiza ações em resposta ao pressionamento de um botão. Ele permite controlar o dispositivo usando apenas um ou dois botões.
Para ajudar as pessoas com necessidades de acessibilidade a usar seu app, ele precisa seguir as práticas recomendadas descritas nesta página. Elas se baseiam nas diretrizes descritas em Tornar os apps mais acessíveis.
Cada uma dessas práticas recomendadas, descritas nas seções a seguir, pode melhorar ainda mais a acessibilidade do seu app:
- Elementos de etiqueta
- Os usuários precisam entender o conteúdo e a finalidade de cada elemento interativo e significativo da interface no seu app.
- Adicionar ações de acessibilidade
- Ao adicionar ações de acessibilidade, você permite que usuários de serviços de acessibilidade concluam fluxos de usuários importantes no seu app.
- Usar recursos de acessibilidade integrados
- O Compose oferece muitos comportamentos de acessibilidade por padrão. Aproveite os comportamentos de acessibilidade predefinidos para tornar seus componentes acessíveis com pouco ou nenhum trabalho extra. O Compose também oferece maneiras de atender a requisitos de acessibilidade mais específicos que não são cobertos pelos recursos padrão.
- Usar outras indicações além da cor
- Os usuários precisam conseguir distinguir claramente as categorias de elementos em uma interface. Para fazer isso, use padrões e posicionamento junto à cor para expressar essas diferenças.
- Tornar o conteúdo de mídia mais acessível
- Adicione descrições ao conteúdo de áudio ou vídeo do seu app para que os usuários que consomem esse conteúdo não precisem depender de indicações completamente visuais ou auditivas.
Elementos de etiqueta
É importante oferecer aos usuários etiquetas descritivas e úteis para cada elemento da interface interativo do seu app. Cada etiqueta precisa explicar a semântica de um elemento específico, ou seja, o significado e a finalidade dele. Leitores de tela como o TalkBack podem anunciar essas etiquetas para os usuários.
Na maioria dos casos, as APIs do Compose e o Material têm compatibilidade com acessibilidade padrão. No entanto, se você precisar especificar manualmente as propriedades semânticas de um elemento de interface, use o modificador semantics e a propriedade contentDescription. Para mais informações sobre semântica, consulte
Semântica.
As seções a seguir descrevem várias outras técnicas de rotulagem.
Elementos editáveis
Ao classificar elementos editáveis, como campos de texto, é interessante mostrar um texto que dê um exemplo de entrada válida no próprio elemento, além de disponibilizar esse exemplo de texto para os leitores de tela. Nessas situações, é possível usar texto de espaço reservado, também chamado de texto de dica.
No exemplo a seguir, o TextField tem um parâmetro placeholder que
fornece texto de dica.
val usernameState = rememberTextFieldState() TextField( state = usernameState, lineLimits = TextFieldLineLimits.SingleLine, placeholder = { Text("Enter Username") } )
Também é comum que um campo de texto tenha um rótulo descritivo correspondente que descreva o que os usuários precisam inserir como entrada.
No exemplo a seguir, o TextField tem um parâmetro label que fornece
uma descrição de acessibilidade.
TextField( state = rememberTextFieldState(initialText = "Hello"), label = { Text("Label") } )
Para mais informações sobre texto e entrada do usuário, consulte Configurar campos de texto.
Elementos em uma coleção
Ao adicionar rótulos aos elementos de uma coleção, cada rótulo precisa ser único. Dessa forma, os serviços de acessibilidade do sistema podem se referir a exatamente um elemento na tela quando anunciam uma etiqueta. Essa correspondência permite que os usuários saibam quando percorreram a interface ou mudaram o foco para um elemento que já conhecem.
Por exemplo, quando você tem um LazyColumn ou LazyRow, use o modificador semantics
para atribuir um collectionItemInfo exclusivo a cada item, conforme mostrado no
snippet a seguir:
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) } ) } }
Para mais informações sobre propriedades semânticas para listas e grades, consulte Informações de lista e item.
Grupos de conteúdo relacionado
Caso seu app exiba vários elementos de UI que formam um grupo natural, como
detalhes de uma música ou atributos de uma mensagem, organize esses elementos em um
contêiner pai (como Column, Row ou Box). Use o modificador semantics do contêiner pai
para definir mergeDescendants como true.
Dessa forma, os serviços de acessibilidade podem apresentar as descrições de conteúdo dos elementos internos, um após o outro, em um único anúncio. Consolidar elementos relacionados ajuda os usuários de tecnologia adaptativa a descobrir as informações na tela com mais eficiência.
No snippet a seguir, o elemento combinável Row atua como o contêiner principal.
Dentro do Row, há elementos relacionados que mostram metadados de uma postagem de blog: o avatar e o nome do autor, além do tempo estimado de leitura.
Definir mergeDescendants como true agrupa esses elementos internos para que
os serviços de acessibilidade possam tratá-los como uma unidade.
@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") } } }
Ao agrupar elementos relacionados, como no exemplo anterior, torne apenas o contêiner pai interativo. Evite adicionar modificadores clickable ou focusable aos elementos filhos internos. Em vez disso, aplique os modificadores ao Row ou Column principal.
Como os serviços de acessibilidade anunciam as descrições dos elementos internos em uma única expressão, é importante manter cada descrição o mais curta possível, sem deixar de transmitir o significado do elemento.
Observação:em geral, ao criar uma descrição de conteúdo para um grupo, evite agregar o texto dos filhos dele. Isso torna a descrição do grupo frágil, e quando o texto de um filho muda, a descrição do grupo pode não corresponder mais ao texto visível.
Em uma lista ou grade, um leitor de tela pode consolidar o texto dos nós de texto filhos de um elemento. É melhor evitar modificar esse aviso.
Para mais informações sobre como mesclar semânticas, consulte Mesclar e limpar.
Títulos no texto
Alguns apps usam títulos para resumir grupos de texto que aparecem na tela. Se um elemento específico representa um título, você pode indicar a finalidade dele para os serviços de acessibilidade definindo a propriedade heading no modificador semantics.
@Composable private fun Subsection(text: String) { Text( text = text, style = MaterialTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() } ) }
Os usuários de serviços de acessibilidade podem optar por navegar entre títulos em vez de entre parágrafos ou palavras. Essa flexibilidade melhora a experiência de navegação de texto.
Para mais informações sobre a propriedade semântica heading, consulte Cabeçalhos.
Títulos do painel de acessibilidade
No Android 9 (API nível 28) ou versões mais recentes, você pode fornecer títulos de fácil acessibilidade para os painéis de uma tela. Para fins de acessibilidade, um painel é uma parte visualmente distinta de uma janela.
Para que os serviços de acessibilidade entendam o comportamento semelhante a janelas de um painel, disponibilize títulos descritivos para os painéis do seu app. Os serviços de acessibilidade podem oferecer informações mais detalhadas aos usuários quando a aparência ou o conteúdo de um painel muda.
ShareSheet( message = "Choose how to share this photo", modifier = Modifier .fillMaxWidth() .align(Alignment.TopCenter) .semantics { paneTitle = "New bottom sheet" } )
Para mais informações sobre a propriedade semântica paneTitle, consulte
Componentes semelhantes a janelas.
Elementos decorativos
Se um elemento na sua interface existir apenas para fins de espaçamento ou aparência visual, defina as propriedades apropriadas no elemento para indicar que os serviços de acessibilidade podem ignorá-lo.
Para elementos combináveis Image ou Icon, defina contentDescription = null. Para outros elementos puramente decorativos que não fornecem contexto nem funcionalidade, use hideFromAccessibility. Essa propriedade semântica informa aos serviços de acessibilidade
para ignorar o item.
Se um elemento combinável interativo tiver elementos filhos decorativos e não interativos,
use clearAndSetSemantics para garantir que os serviços de acessibilidade
não os percorram. Observe que clearAndSetSemantics apaga completamente a semântica padrão de um elemento e dos filhos dele. Isso permite definir um novo elemento de acessibilidade unificado. Normalmente, você usa essa abordagem para componentes personalizados complexos.
No exemplo a seguir, Icon e Text são elementos filhos decorativos
dentro de uma alternância personalizada. Para impedir que os serviços de acessibilidade percorram
essas crianças individualmente, limpe a semântica delas usando
clearAndSetSemantics no elemento pai Row. Isso informa aos serviços de acessibilidade
para tratar todo o Row como uma alternância navegável:
// 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?") } }
Para mais informações sobre como limpar a semântica, consulte Limpar e definir semântica.
Adicionar ações de acessibilidade
É importante garantir que os usuários de serviços de acessibilidade tenham uma maneira de concluir todos os fluxos de usuários no seu app.
Se a interação do elemento combinável personalizado mudar o estado do app de uma maneira
não óbvia, forneça rótulos descritivos para ações de toque padrão usando
parâmetros como onClickLabel ou onLongClickLabel em Modifier.clickable
ou Modifier.combinedClickable.
Para interações complexas que não podem ser mapeadas para toques padrão, use customActions.
Por exemplo, se o app permitir que os usuários arrastem um item para outro local ou deslizem em um item de uma lista, você pode oferecer uma maneira alternativa de concluir esses fluxos de usuários expondo a ação aos serviços de acessibilidade. Assim, os usuários do TalkBack, do Voice Access ou do Acesso com interruptor podem realizar ações que, de outra forma, estariam disponíveis apenas por gestos.
No Compose, é possível definir ações de acessibilidade personalizadas usando a
propriedade customActions no modificador semantics, com
CustomAccessibilityAction.
Por exemplo, se o app permitir que os usuários deslizem um item para dispensá-lo, você poderá expor a funcionalidade por uma ação de acessibilidade personalizada:
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() }
Com a ação de acessibilidade personalizada implementada, os usuários podem acessar a ação no menu de ações.
Para mais informações sobre ações personalizadas, consulte Ações personalizadas.
Tornar as ações disponíveis compreensíveis
Quando um elemento da interface oferece suporte a ações como tocar e manter pressionado, um serviço de acessibilidade como o TalkBack anuncia isso como "Toque duas vezes e mantenha pressionado para tocar e pressionar".
Esse anúncio genérico não dá ao usuário nenhum contexto sobre o que uma ação de tocar e pressionar faz.
Para tornar esse anúncio mais útil, especifique uma descrição significativa para a ação.
No Compose, modificadores de interação padrão, como clickable e combinedClickable, têm parâmetros integrados (onClickLabel e onLongClickLabel) que podem ser usados para fornecer descrições das ações, como no exemplo a seguir:
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 } ) }
Assim, o TalkBack anuncia "Abrir menu de contexto", ajudando os usuários a entender o propósito da ação.
Também é possível especificar um rótulo diretamente no modificador semantics.
Para mais informações sobre como responder a toques e cliques, consulte Tocar e pressionar e Elementos interativos.
Usar recursos de acessibilidade integrados
Ao projetar a interface do app, aproveite os recursos de acessibilidade integrados para evitar a reimplementação de funcionalidades que já existem. As APIs Material, Compose UI e Foundation implementam e oferecem muitas práticas acessíveis por padrão.
No Jetpack Compose, use elementos combináveis integrados, como Button, Switch e Checkbox, para criar interfaces acessíveis. Esses componentes vêm pré-empacotados com modificadores semantics, como role e stateDescription, que podem ser usados para tornar seus apps mais acessíveis.
Aplicar semântica a componentes personalizados
Ao criar um componente personalizado, pense em que tipo de suporte de acessibilidade
ele precisa para cumprir a função. Muitas vezes, as APIs padrão do
Compose que você já usa, como clickable, toggleable ou
selectable, são suficientes porque preenchem automaticamente a árvore
semântica para você.
No entanto, alguns componentes exigem informações mais específicas do que os modificadores padrão oferecem. Nesses casos, procure modificadores especializados (como
triStateToggleable) ou, se não houver nenhum, forneça explicitamente a semântica usando
o Modifier.semantics de baixo nível.
Por exemplo, considere um TriStateSwitch, um interruptor com três estados (ativado, desativado e indeterminado).
Enquanto um modificador toggleable padrão assume dois estados, o
modificador triStateToggleable processa a complexidade do terceiro estado. Ele define automaticamente a acessibilidade Role (Switch) e State. Assim, os serviços de acessibilidade recebem informações precisas, e você não precisa definir a semântica manualmente.
O snippet de código a seguir mostra um TriStateSwitch usando essa abordagem:
@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 } } )
Ao criar um componente personalizado, forneça todas as propriedades semânticas relevantes para fins de acessibilidade. Por exemplo, se o componente imitar
um controle padrão, como uma chave ou um botão, essas propriedades vão incluir a
função do componente (como Role.Switch ou Role.Button), stateDescription
(como "Ativado", "Desativado", "Marcado" ou "Não marcado") e todos os rótulos de ação
relevantes. Para mais informações, consulte Componentes personalizados.
Usar outras indicações além da cor
Para ajudar os usuários com deficiências visuais relacionadas a cores, use outros tipos de indicador para distinguir os elementos da IU nas telas do seu app. Essas técnicas podem incluir o uso de diferentes formas ou tamanhos, disponibilização de texto ou padrões visuais ou adição de retorno tátil baseado em áudio ou toque para marcar as diferenças dos elementos.
A Figura 1 mostra duas versões de uma atividade. Uma versão usa somente cores para diferenciar duas ações possíveis em um fluxo de trabalho. A outra versão usa a prática recomendada de incluir formas e texto, além de cores, para destacar as diferenças entre as duas opções:
Tornar o conteúdo de mídia mais acessível
Se você estiver desenvolvendo um app que inclui conteúdo de mídia, como um trecho de vídeo ou gravação de áudio, faça o possível para ajudar os usuários com diferentes tipos de necessidades de acessibilidade a entender o material. Em especial, tente fazer o seguinte:
- Inclua controles que permitam aos usuários pausar ou interromper a mídia, mudar o volume e alternar as legendas.
- Se um vídeo apresentar informações essenciais para a conclusão de um fluxo de trabalho, disponibilize o mesmo conteúdo em um formato alternativo, como uma transcrição.
Outros recursos
Para saber mais sobre como tornar seu app mais acessível, consulte estes recursos extras: