Compatibilidade com conteúdo escalonável pelo usuário

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.