Implemente gestos de pinça para zoom e ofereça suporte a conteúdo escalonável no app. Esse é o método padrão e consistente da plataforma para melhorar a acessibilidade, permitindo que os usuários ajustem intuitivamente o tamanho do texto e dos elementos da interface do usuário para atender às necessidades deles. Seu app pode definir um comportamento de escalonamento personalizado com controle granular e contextual que oferece uma experiência que os usuários costumam descobrir mais rapidamente do que um recurso no nível do sistema, como a ampliação da tela.
Escolher uma estratégia de escalonamento
As estratégias abordadas neste guia fazem com que a interface reflua e se reorganize para se ajustar à largura da tela. Isso oferece um benefício significativo de acessibilidade, eliminando a necessidade de panorâmica horizontal e o movimento frustrante de "zigue-zague" que seria necessário para ler longas linhas de texto.
Leitura complementar: pesquisas confirmam que, para usuários com baixa visão, o ajuste do conteúdo é muito mais legível e fácil de navegar do que interfaces que exigem panorâmica bidimensional. Para mais detalhes, consulte Uma comparação entre conteúdo de pan-and-scan e de refluxo em dispositivos móveis.
Escalonar todos os elementos ou apenas os de texto
A tabela a seguir demonstra o efeito visual de cada estratégia de escalonamento.
| Estratégia | Dimensionamento de densidade | Ajuste da fonte |
|---|---|---|
Comportamento |
Redimensiona tudo proporcionalmente. O conteúdo é reformatado para se ajustar ao contêiner, assim o usuário não precisa rolar a tela na horizontal para ver tudo. |
Afeta apenas elementos de texto. O layout geral e os componentes não textuais permanecem do mesmo tamanho. |
O que é escalonamento |
Todos os elementos visuais: texto, componentes (botões, ícones), imagens e espaçamento do layout (padding, margens) |
Somente texto |
Demonstração |
Recomendações
Agora que você viu as diferenças visuais, a tabela a seguir ajuda a avaliar as compensações e escolher a melhor estratégia para seu conteúdo.
Tipo de interface |
Estratégia recomendada |
Raciocínio |
Layouts com muita leitura Exemplos: artigos de notícias, apps de mensagens |
Escalonamento de densidade ou de fonte |
É preferível usar o ajuste de escala de densidade para dimensionar toda a área de conteúdo, incluindo imagens inline. O ajuste de escala da fonte é uma alternativa simples se apenas o texto precisa ser ajustado. |
Layouts visualmente estruturados Exemplos: lojas de apps, feeds de redes sociais |
Escalonamento de densidade |
Preserva as relações visuais entre imagens e texto em carrosséis ou grades. A natureza de reflow evita o movimento horizontal, que entraria em conflito com elementos de rolagem aninhados. |
Detectar gestos de escalonamento no Jetpack Compose
Para oferecer suporte a conteúdo escalonável pelo usuário, primeiro é preciso detectar gestos multitoque. No
Jetpack Compose, isso pode ser feito usando o Modifier.transformable.
O modificador transformable é uma API de alto nível que fornece o delta zoomChange desde o último evento de gesto. Isso simplifica a lógica de atualização de estado para
acumulação direta (por exemplo, scale *= zoomChange), tornando-a ideal para
as estratégias de escalonamento adaptativo abordadas neste guia.
Exemplos de implementações
Os exemplos a seguir mostram como implementar as estratégias de escalonamento de densidade e de fonte.
Dimensionamento de densidade
Essa abordagem dimensiona a base density de uma área da interface. Como resultado, todas as medidas baseadas em layout, incluindo padding, espaçamento e tamanhos de componentes, são dimensionadas como se o tamanho ou a resolução da tela tivesse mudado. Como o tamanho do texto também depende da densidade, ele também é dimensionado proporcionalmente. Essa estratégia é eficaz quando você quer ampliar uniformemente todos os elementos em uma área específica, mantendo o ritmo visual geral e as proporções da interface.
private class DensityScalingState( // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x. private val minScale: Float = 0.75f, private val maxScale: Float = 3.5f, private val currentDensity: Density ) { val transformableState = TransformableState { zoomChange, _, _ -> scaleFactor.floatValue = (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale) } val scaleFactor = mutableFloatStateOf(1f) fun scaledDensity(): Density { return Density( currentDensity.density * scaleFactor.floatValue, currentDensity.fontScale ) } }
Ajuste da fonte
Essa estratégia é mais segmentada, modificando apenas o fator fontScale. O resultado é que apenas os elementos de texto aumentam ou diminuem, enquanto todos os outros componentes de layout, como contêineres, padding e ícones, permanecem com um tamanho fixo. Essa estratégia é adequada para melhorar a legibilidade do texto em apps de leitura intensiva.
class FontScaleState( // Note: For accessibility, typical min/max values are ~0.75x and ~3.5x. private val minScale: Float = 0.75f, private val maxScale: Float = 3.5f, private val currentDensity: Density ) { val transformableState = TransformableState { zoomChange, _, _ -> scaleFactor.floatValue = (scaleFactor.floatValue * zoomChange).coerceIn(minScale, maxScale) } val scaleFactor = mutableFloatStateOf(1f) fun scaledFont(): Density { return Density( currentDensity.density, currentDensity.fontScale * scaleFactor.floatValue ) } }
Interface de demonstração compartilhada
Esse é o elemento combinável DemoCard compartilhado usado pelos dois exemplos anteriores
para destacar os diferentes comportamentos de escalonamento.
@Composable private fun DemoCard() { Card( modifier = Modifier .width(360.dp) .padding(16.dp), shape = RoundedCornerShape(12.dp) ) { Column( modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { Text("Demo Card", style = MaterialTheme.typography.headlineMedium) var isChecked by remember { mutableStateOf(true) } Row(verticalAlignment = Alignment.CenterVertically) { Text("Demo Switch", Modifier.weight(1f), style = MaterialTheme.typography.bodyLarge) Switch(checked = isChecked, onCheckedChange = { isChecked = it }) } Row(verticalAlignment = Alignment.CenterVertically) { Icon(Icons.Filled.Person, "Icon", Modifier.size(32.dp)) Spacer(Modifier.width(8.dp)) Text("Demo Icon", style = MaterialTheme.typography.bodyLarge) } Row( Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween ) { Box( Modifier .width(100.dp) .weight(1f) .height(80.dp) .background(Color.Blue) ) Box( Modifier .width(100.dp) .weight(1f) .height(80.dp) .background(Color.Red) ) } Text( "Demo Text: Lorem ipsum dolor sit amet, consectetur adipiscing elit," + " sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", style = MaterialTheme.typography.bodyMedium, textAlign = TextAlign.Justify ) } } }
Dicas e considerações
Para criar uma experiência mais refinada e acessível, considere as seguintes recomendações:
- Considere oferecer controles de escala sem gestos: alguns usuários podem ter dificuldade com gestos. Para oferecer suporte a esses usuários, considere fornecer uma maneira alternativa de ajustar ou redefinir a escala que não dependa de gestos.
- Crie para todas as escalas: teste sua interface com o dimensionamento no app e as configurações de fonte ou tela em todo o sistema. Verifique se os layouts do app se adaptam corretamente sem quebrar, sobrepor ou ocultar conteúdo. Saiba como criar layouts adaptáveis.