Ao testar a interface multilíngue do Flutter, encontramos “300 BPM” dividido em duas linhas

Testamos a exibição do SANGE Metronome combinando 12 idiomas, 6 tamanhos de tela e 3 escalas de texto. A quebra de linha de “300 BPM” e mensagens de erro longas motivaram correções na interface e a revisão das verificações dos testes automatizados.

Publicado Atualizado
  • Suporte a vários idiomas
  • Flutter
  • Testes de interface
  • desenvolvimento pessoal

Verificamos a exibição em telas pequenas e com texto ampliado no “SANGE Metronome – Prática simples de ritmo”, aplicativo que desenvolvemos de forma independente.

Um dos problemas encontrados foi o número em “300 BPM”, exibido nos favoritos, se dividir em “30” e “0”. O texto não ultrapassava a tela. Ainda assim, o valor do andamento ficava difícil de ler.

Foi necessário verificar separadamente se o layout não gerava exceções e se as informações necessárias podiam ser lidas.

Neste artigo, contamos quais problemas de exibição encontramos nos testes de widgets em 12 idiomas e nas verificações de tela no emulador Android, e como os incorporamos às correções e aos testes.

Visão geral da parte inferior da tela inicial em francês, português do Brasil, indonésio, tailandês, vietnamita e japonês, com escala de texto de 130%
Visão geral de seis telas após a correção. Na linha superior, da esquerda para a direita: francês, português do Brasil e indonésio. Na inferior: tailandês, vietnamita e japonês. Os nomes em alemão dos favoritos são dados de teste comuns a todos os idiomas, usados para testar nomes longos.

Um layout que funciona em japonês pode não funcionar da mesma forma em outros idiomas

A tela do metrônomo exibe não apenas o andamento, mas também batidas, nomes de ritmos, volume e nomes de favoritos. A tela de salvamento também precisa de campos de entrada, explicações de erros e botões Salvar e Cancelar.

Mesmo que um layout caiba em japonês, o tamanho dos rótulos muda com a tradução. Por exemplo, “12拍” em japonês e “12 Schläge” em alemão exigem larguras diferentes para o botão.

Ao aumentar o texto, os elementos dispostos lado a lado deixam de caber. Por isso, decidimos não apenas trocar o idioma, mas combinar tamanho de tela, escala de texto e tela exibida nas verificações.

Verificação automatizada com 12 idiomas, 6 tamanhos e 3 escalas de texto

Nos testes de widgets, combinamos as condições a seguir. Esses testes renderizam os componentes de interface do Flutter em um ambiente de teste para verificá-los.

Dimensão da verificaçãocondições
IdiomaJaponês, inglês, espanhol, português do Brasil, alemão, francês, coreano, indonésio, vietnamita, tailandês, chinês tradicional e italiano
Tamanho lógico, orientação retrato320×568、360×640、360×800、393×873、412×915、432×960
Escala do texto100%, 130% e 200%
TelaInício, batidas, subdivisão rítmica, configurações, seleção de idioma, salvamento, gerenciamento de favoritos e lista de favoritos
12 idiomas × 6 tamanhos × 3 escalas de texto × 8 telas = 1,728 condições

Os dados de teste incluíram 300 BPM, 12 batidas, semicolcheias, volume de 100% e três favoritos com nomes longos. Na tela de salvamento, também exibimos o erro de nome duplicado.

A escala do texto foi definida com TextScaler.linear. Os valores de 100%, 130% e 200% desta verificação são condições de ampliação linear e não reproduzem integralmente todas as formas de ampliação oferecidas pelas configurações do sistema de dispositivos reais.

Também coletamos imagens no emulador Android, em sete idiomas: alemão, francês, português do Brasil, indonésio, tailandês, vietnamita e japonês. Não testamos todas as combinações de tamanhos, escalas e idiomas. Verificamos os tamanhos de tela e as escalas em alemão; os outros seis idiomas foram verificados com configuração de 360×640 e escala de 130%.

No emulador, as barras do sistema reduzem a área disponível para o aplicativo. Além do tamanho configurado, registramos o tamanho lógico durante a renderização e as dimensões dentro da SafeArea.

Ajustar as colunas dos botões de batida para acomodar o texto

O primeiro problema encontrado foi o texto explicativo do andamento e a unidade das batidas ultrapassando a borda direita. O emulador Android também detectou RenderFlex overflow, o que exigiu uma revisão do layout.

Os botões de seleção de batidas também usavam quatro colunas fixas. Porém, com rótulos traduzidos mais longos ou uma escala de texto maior, essa quantidade de colunas não oferecia largura suficiente.

Passamos a medir os rótulos traduzidos com TextPainter e a determinar o número de colunas pela largura necessária, incluindo a escala do texto. Em condições estreitas, reduzimos as colunas e organizamos os botões verticalmente.

Tela corrigida de seleção de batidas, com configuração de 320×568 e alemão a 100%, mostrando os botões de 1 a 12 batidas em duas colunas
Exibição a 100% após a correção. Nessa condição, os 12 botões couberam em duas colunas.
Seleção de batidas com configuração de 320×568 e alemão a 200%, após rolar para baixo. Os botões de 7 a 12 batidas aparecem em uma coluna
Com o mesmo tamanho de exibição e escala de 200%, passamos a uma coluna. Rolamos até o botão de 12 batidas e a explicação abaixo dele. A escala de texto e a posição de rolagem diferem da imagem anterior; ambas mostram o estado após a correção.

Na tela inicial, também revimos o layout que tentava acomodar nomes longos de ritmos em duas colunas estreitas, passando a empilhar batidas e ritmo quando necessário. Para evitar a divisão dos números das batidas 10 a 12, permitimos que o conjunto dos indicadores de batida se distribua por várias linhas.

A divisão de “300” nem sempre gera uma exceção

Ao examinar as imagens, encontramos o problema nos cartões de favoritos com configuração de 320×568 e escala de texto de 200%.

Como os cartões continuavam organizados em três colunas, o número “300” quebrava no meio. Mesmo que o texto caiba na área de exibição, dividi-lo em “30” e “0” dificulta a leitura do andamento.

Esse problema não pôde ser detectado apenas pela verificação de exceções de layout.

A correção ajustou o número de colunas dos cartões de favoritos de acordo com a escala do texto. Na tela pequena com escala de 200% desta verificação, passamos a uma coluna para evitar a divisão dos dígitos do andamento.

Tela corrigida com configuração de 320×568 e alemão a 200%, mostrando os favoritos em uma coluna na parte inferior da tela inicial e os dígitos de 300 BPM sem divisão
Favoritos após a correção. O final dos nomes longos é truncado, enquanto os dígitos do andamento permanecem juntos. Como não salvamos uma imagem anterior à correção nessas condições, esta não é uma comparação lado a lado de antes e depois nas mesmas condições.

Junto com a correção, acrescentamos aos testes automatizados a verificação de que um BPM de três dígitos permaneça em uma linha. A seguir está um trecho dessa verificação.

for (var card = 0; card < 3; card++) {
  final paragraph = tester.renderObject<RenderParagraph>(
    find.text('300  BPM').at(card),
  );
  expect(
    paragraph.getBoxesForSelection(
      const TextSelection(baseOffset: 0, extentOffset: 3),
    ),
    hasLength(1),
    reason:
        '$locale/$size/$scale favorite BPM must stay on one line',
  );
}

Verificamos se o intervalo de caracteres correspondente a “300” ocupava uma única caixa de renderização. Nos testes completos, verificamos o BPM de cada um dos três favoritos e os números de batida de 1 a 12 na tela inicial.

Este método se aplica aos números renderizados com a mesma fonte nesta verificação. Ele não é um método geral para identificar quebras de linha em textos que misturam idiomas ou fontes diferentes.

Definir verificações concretas com base nas informações que queremos exibir. Um aprendizado desta rodada foi incorporar os problemas encontrados nas imagens aos testes automatizados, para detectá-los novamente em futuras alterações.

É possível ler a explicação do erro e acessar o botão Salvar?

Na tela de salvamento, também revimos o limite de linhas das mensagens de erro.

Antes, o texto era limitado a três linhas, mas traduções longas poderiam deixar de caber em telas estreitas com texto ampliado. Removemos esse limite para permitir a leitura da explicação completa com rolagem.

Os botões Salvar e Cancelar passaram a ficar empilhados em telas estreitas ou com texto grande. Também ajustamos o título e o botão de fechar do modal, assim como os nomes das configurações e seus valores selecionados, para reservar mais largura ao texto.

Tela de salvamento com configuração de 320×568 e alemão a 200%, após rolar para baixo, mostrando a mensagem completa de nome duplicado e os botões Cancelar e Salvar empilhados
Explicação do erro de nome duplicado e botões Cancelar e Salvar. A tela foi capturada após a rolagem.

Também acrescentamos verificações durante a digitação. Nos testes de widgets, reservamos uma margem inferior de 280 pixels lógicos equivalente ao teclado e verificamos se, após a rolagem, o botão Salvar aparecia acima dessa área. Também verificamos se o limite de linhas não truncava as mensagens de erro.

No emulador Android, demos foco ao campo de entrada e verificamos o layout com o teclado aberto. Porém, os PNGs coletados nessa situação capturam apenas a tela Flutter: o próprio teclado do sistema não aparece. Registramos separadamente as imagens da exibição normal e da digitação.

Resultados após as correções e alcance da verificação

Estes são os resultados da verificação realizada em 30 de outubro de 2026.

ArtigoResultado
Testes de widgets de exibiçãoNenhuma exceção de layout em 1,728 condições. As verificações de divisão de números, truncamento de mensagens de erro e acesso ao botão Salvar também passaram nas telas correspondentes
Todos os testes Flutter121 testes aprovados
Análise estáticaNenhum problema apontado
Condições de tela no emulador Android280 condições. Em cada execução, layoutErrors foi 0
PNGs coletados478 imagens, incluindo estados após a rolagem e durante a digitação

1,728 é o número de combinações de condições de exibição, enquanto 121 é o total de testes Flutter executados. Como os testes verificam repetidamente várias condições de exibição, esses números têm significados diferentes.

O número 478 corresponde aos PNGs coletados. Não atribuímos um resultado visual individual de aprovação ou reprovação a todas as imagens; selecionamos telas principais para verificar caracteres cortados ou sobrepostos, números divididos e a exibição após a rolagem. Nas telas principais verificadas em tailandês e vietnamita, não observamos quadrados de caracteres ausentes nem sobreposição de texto.

Além dos seis tamanhos sintéticos, usamos seis configurações de exibição no emulador: Galaxy A16 5G, A06 4G, S24+, S23, Redmi 14C 4G e Pixel 9. Preparamos 30 configurações específicas de modelos, mas executamos seis delas nesta rodada.

Aplicamos resoluções e densidades aproximadas para teste ao mesmo emulador Android 14. Não reproduzimos sistemas personalizados de fabricantes, fontes ou recortes de câmera, nem testamos 30 modelos em dispositivos reais. Os testes Flutter foram executados no Windows; também não executamos a comparação golden de pixels para Linux nesta rodada.

Este registro trata da verificação da exibição. Os resultados de renderização, foco no campo de entrada e rolagem não comprovam o sucesso da reprodução de áudio nem do processo de salvamento.

O que continuar verificando nas próximas alterações de interface

Esta verificação tornou mais concretos os itens que queremos manter nos testes de exibição.

  • Não dividir no meio números como andamento e índices de batida.
  • Permitir a leitura completa das explicações de erro.
  • Manter os botões necessários acessíveis com texto ampliado e durante a digitação.

Ao ajustar o número de colunas ao tamanho do texto e às traduções, e usar disposição vertical e rolagem, reservamos espaço para as informações e operações necessárias.

Repetir as condições nos testes automatizados e incorporar às verificações os problemas percebidos nas imagens renderizadas. Ao manter esse fluxo, poderemos verificar se os problemas encontrados nesta rodada reaparecem nas próximas alterações da interface.

← Vá para a lista de artigos do blog de desenvolvimento