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 aos 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 usando uma voz sintetizada e realiza ações em um app em resposta às interações do usuário.
- Acesso com interruptor: ajuda pessoas com deficiências motoras. Ele destaca elementos interativos e executa ações em resposta ao usuário pressionando um botão. Ele permite controlar o dispositivo usando apenas um ou dois botões.
Para ajudar pessoas com necessidades de acessibilidade a usar seu app, é necessário seguir as práticas recomendadas descritas nesta página, que 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 do app.
- Adicionar ações de acessibilidade
- Ao adicionar ações de acessibilidade, você permite que os usuários de serviços de acessibilidade concluam fluxos do usuário críticos 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 vídeo ou áudio do app para que os usuários que consomem esse conteúdo não precisem depender de dicas totalmente visuais ou auditivas.
Elementos de etiqueta
É importante fornecer aos usuários rótulos úteis e descritivos para cada elemento interativo da interface no app. Cada rótulo 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 esses rótulos aos usuários.
Na maioria dos casos, as APIs do Compose e o Material têm
suporte padrão à acessibilidade. No entanto, se você precisar especificar manualmente
as propriedades semânticas de um elemento da 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 rotular elementos editáveis, como campos de texto, é útil mostrar um texto que dê um exemplo de entrada válida no próprio elemento, além de disponibilizar esse texto de exemplo para leitores de tela. Nessas situações, é possível usar um texto de preenchimento, também chamado de texto de dica.
No exemplo a seguir, o TextField tem um parâmetro placeholder que
fornece um 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 descreve 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 exclusivo. Dessa forma, os serviços de acessibilidade do sistema podem se referir a exatamente um elemento na tela ao anunciar um rótulo. Essa correspondência permite que os usuários saibam quando percorrem a IU ou quando movem o foco para um elemento que já descobriram.
Por exemplo, quando você tiver um LazyColumn ou LazyRow, use o modificador semantics
para atribuir uma collectionItemInfo exclusiva a cada item, conforme mostrado no
snippet abaixo:
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 as propriedades de semântica para listas e grades, consulte Informações de listas e itens.
Grupos de conteúdo relacionado
Se o app mostra vários elementos da interface 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 uma após a outra, em um único anúncio. A consolidação de 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 pai.
Dentro do Row, há elementos relacionados que mostram metadados de uma postagem de blog:
o avatar do autor, o nome do autor e o tempo estimado de leitura.
Definir mergeDescendants como true agrupa esses elementos internos para que
os serviços de acessibilidade possam tratá-los como uma única 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 interativo apenas o
contêiner pai. Evite adicionar modificadores clickable ou focusable
aos elementos filhos internos. Em vez disso, aplique os modificadores ao Row
ou Column pai.
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. 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 um contexto de lista ou grade, um leitor de tela pode consolidar o texto dos nós de texto filhos de um elemento de lista ou grade. É melhor evitar modificar esse anúncio.
Para mais informações sobre a semântica de mesclagem, 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 representar um título, você poderá indicar a finalidade dele
para 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 de semântica heading, consulte Títulos.
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 de um painel, dê títulos descritivos aos painéis do 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 de semântica paneTitle, consulte
Componentes semelhantes a janelas.
Elementos decorativos
Se um elemento na interface existe 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 ou 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 processem. O clearAndSetSemantics apaga totalmente a semântica
padrão de um elemento e dos filhos dele. Isso permite definir um novo elemento de acessibilidade
unificado. Normalmente, essa abordagem é usada para componentes personalizados
complexos.
No exemplo a seguir, Icon e Text são elementos filhos decorativos
dentro de um botão de alternância personalizado. Para evitar que os serviços de acessibilidade percorram
esses filhos individualmente, limpe a semântica deles usando
clearAndSetSemantics no Row pai. Isso informa aos serviços de acessibilidade
que devem tratar todo o Row como uma alternância que pode ser percorrida:
// 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 a semântica.
Adicionar ações de acessibilidade
É importante garantir que os usuários de serviços de acessibilidade possam concluir todos os fluxos do usuário no seu app.
Se a interação do elemento de composição personalizado mudar o estado do app de uma forma que
não seja ó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 permite 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 do usuário expondo a ação aos serviços de acessibilidade. Dessa forma, os usuários do TalkBack, do Voice Access ou do acesso com interruptor podem realizar ações que, de outra forma, só estariam disponíveis por gestos.
No Compose, é possível definir ações de acessibilidade personalizadas com a
propriedade customActions no modificador semantics, usando
CustomAccessibilityAction.
Por exemplo, se o app permite que os usuários deslizem um item para dispensá-lo, você pode expor a funcionalidade usando 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 acessá-la pelo 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 aceita 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 manter pressionado".
Esse anúncio genérico não dá ao usuário nenhum contexto sobre o que uma ação de tocar e manter pressionado faz.
Para tornar esse anúncio mais útil, especifique uma descrição significativa para a ação.
No Compose, os 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 } ) }
Isso faz com que o TalkBack anuncie "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, considere o tipo de suporte de acessibilidade
necessário para que ele cumpra o papel dele. 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
de semântica para você.
No entanto, alguns componentes exigem informações mais específicas do que as fornecidas pelos modificadores
padrão. 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, uma chave com três estados (ativado,
desativado e indeterminado).
Enquanto um modificador toggleable padrão assume dois estados, o
modificador triStateToggleable lida com a complexidade do terceiro estado. Ele
define automaticamente a acessibilidade Role (Switch) e State. Dessa forma,
os serviços de acessibilidade recebem informações precisas, e você não precisa
definir a semântica manualmente.
O snippet de código abaixo mostra um TriStateSwitch que usa 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 o
papel 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 formas ou tamanhos diferentes, o fornecimento de texto ou padrões visuais ou a adição de feedback de áudio ou toque (tátil) 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 videoclipe ou uma gravação de áudio, tente 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 vitais para concluir um fluxo de trabalho, forneça 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: