Compatibilidade com tamanhos de tela diferentes

Existem dispositivos Android de todos os formatos e tamanhos, portanto, o layout do seu app precisa ser flexível. Ou seja, em vez de definir seu layout com dimensões rígidas que pressuponham determinado tamanho e proporção de tela, seu layout precisa responder de forma eficiente a diferentes tamanhos e orientações.

Ao ser compatível com o maior número possível de telas, seu app pode ser disponibilizado a um número maior de usuários com diferentes dispositivos, usando um único APK. Além disso, flexibilizar o app para diferentes tamanhos de tela garante que ele possa lidar com mudanças de configuração de janela no dispositivo, como quando o usuário ativa o modo de várias janelas.

Esta página mostra como oferecer compatibilidade com diferentes tamanhos de tela por meio das seguintes técnicas:

  • Usar dimensões de visualização que permitam redimensionar o layout.
  • Criar layouts de IU de acordo com a configuração da tela.
  • Fornecer bitmaps que possam se esticar com as visualizações.

Mas lembre-se de que a adaptação a diferentes tamanhos de tela não necessariamente torna seu app compatível com todos os formatos do Android. Você precisa seguir outras etapas para que ele seja compatível com dispositivos Android Wear, TV, Auto e com o Chrome OS.

Se quiser ver orientações de design para a criação de IU para diferentes telas, consulte as orientações do Material Design para uma IU responsiva (link em inglês).

Criar um layout flexível

Não importa para qual perfil de hardware você quer oferecer compatibilidade primeiro, você precisa criar um layout que seja responsivo às menores variações possíveis de tamanho de tela.

Usar ConstraintLayout

A melhor forma de criar um layout responsivo para diferentes tamanhos de tela é usar ConstraintLayout como o layout básico na IU. ConstraintLayout permite especificar a posição e o tamanho de cada visualização de acordo com as relações espaciais com outras visualizações no layout. Dessa forma, todas as visualizações podem se mover e expandir juntas quando o tamanho da tela muda.

A maneira mais fácil de criar um layout com ConstraintLayout é usar o Layout Editor no Android Studio. Ele permite que você arraste novas visualizações para o layout, anexe as limitações da visualização mãe e outras visualizações irmãs e edite as propriedades da visualização, tudo isso sem editar qualquer XML manualmente (veja a Figura 1).

Para mais informações, consulte Criar uma IU responsiva com o ConstraintLayout.

Figura 1. O Layout Editor no Android Studio mostrando um arquivo ConstraintLayout.

O ConstraintLayout não resolve todos os cenários de layout, principalmente em listas carregadas dinamicamente, para as quais é necessário usar RecyclerView. No entanto, independentemente do layout usado, você sempre precisa evitar a codificação de tamanhos de layout. Consulte a próxima seção.

Evitar tamanhos de layout codificados

Para garantir que o layout seja flexível e se adapte a diferentes tamanhos de tela, use "wrap_content" e "match_parent" para a largura e a altura da maioria dos componentes de visualização, em vez de tamanhos codificados.

"wrap_content" instrui a visualização a definir o próprio tamanho como for necessário para ajustar o conteúdo a ela.

"match_parent" faz a visualização expandir o máximo possível dentro da visualização mãe.

Exemplo:

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/lorem_ipsum" />
    

Embora o layout dessa visualização dependa de outros atributos da visualização mãe e de todas as visualizações irmãs, o objetivo do TextView é definir a largura para preencher todo o espaço disponível (match_parent) e definir a altura para exatamente o espaço necessário para o tamanho do texto (wrap_content). Isso permite que a visualização se adapte a diferentes tamanhos de tela e de texto.

A Figura 2 mostra como a largura da visualização de texto usando "match_parent" se ajusta conforme a largura da tela muda pela orientação do dispositivo.

Figura 2. Uma visualização de texto flexível.

Se você usar um LinearLayout, também será possível expandir as visualizações filhas com ponderação de layout para que cada visualização preencha o espaço restante proporcional ao valor ponderado. No entanto, para usar ponderações em um LinearLayout aninhado, é necessário que o sistema realize várias transmissões de layout para determinar o tamanho de cada visualização, diminuindo a velocidade do desempenho da IU. Felizmente, o ConstraintLayout pode atingir quase todos os layouts possíveis com LinearLayout sem impactos no desempenho. Por isso, tente converter seu layout em ConstraintLayout. Depois, você pode definir layouts ponderados com cadeias de restrição.

Criar layouts alternativos

Embora seu layout precise sempre responder a diferentes tamanhos de tela esticando o espaço dentro e em torno das visualizações, isso pode não oferecer a melhor experiência do usuário em todos os tamanhos de tela. Por exemplo, a IU criada para um smartphone provavelmente não oferece uma boa experiência em um tablet. Portanto, seu app também precisa oferecer recursos de layout alternativos para otimizar o design da IU para determinados tamanhos de tela.

Figura 3. O mesmo app usa diferentes layouts para diferentes tamanhos de tela.

Você pode fornecer layouts específicos para cada tela criando outros diretórios res/layout/, um para cada configuração de tela que precisa de um layout diferente. Em seguida, anexe um qualificador de configuração de tela ao nome do diretório layout, como layout-w600dp para telas com 600 dp de largura disponível.

Esses qualificadores de configuração representam o espaço de tela visível disponível para a IU do seu app. O sistema considera todas as decorações, como a barra de navegação, e mudanças na configuração de janelas, como quando o usuário ativa o modo de várias janelas, ao selecionar o layout do seu app.

Para criar um layout alternativo no Android Studio (versão 3.0 ou mais recente), siga estas etapas:

  1. Abra o layout padrão e clique em Orientation for Preview na barra de ferramentas.
  2. Na lista suspensa, clique para criar uma variante sugerida, como Create Landscape Variant ou clique em Create Other.
  3. Se você tiver selecionado Create Other, o Select Resource Directory será exibido. Selecione um qualificador de tela à esquerda e adicione-o à lista de Chosen qualifiers. Quando terminar de adicionar qualificadores, clique em OK. Consulte as seções a seguir para ver informações sobre os qualificadores de tamanho de tela.

Isso cria um arquivo de layout duplicado no diretório adequado para que você possa começar a personalizar o layout para a variante de tela.

Usar o qualificador de menor largura

O qualificador de tamanho de tela de "menor largura" permite que você forneça layouts alternativos para telas que tenham uma largura mínima medida em pixels de densidade independente (dp ou dip).

Ao descrever o tamanho da tela como uma medida em pixels de densidade independente, o Android permite que você crie layouts voltados a dimensões de tela muito específicas, ao mesmo tempo em que evita quaisquer preocupações que possa ter sobre diferentes densidades de pixel.

Por exemplo, é possível criar um layout chamado main_activity otimizado para celulares e tablets criando versões diferentes do arquivo nos diretórios da seguinte forma:

    res/layout/main_activity.xml           # For handsets (smaller than 600dp available width)
    res/layout-sw600dp/main_activity.xml   # For 7” tablets (600dp wide and bigger)
    

O qualificador de menor largura especifica o menor dos dois lados da tela, independentemente da orientação atual do dispositivo. Portanto, essa é uma forma simples de especificar o tamanho de tela disponível para seu layout.

Veja como outros valores de menor largura correspondem a tamanhos de tela típicos:

  • 320 dp: uma tela típica de smartphone (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi etc).
  • 480 dp: uma tela grande de smartphone (aprox. 5 pol.) (480 x 480 mdpi)
  • 600 dp: um tablet de 7 pol. (600 x 1024 mdpi).
  • 720 dp: um tablet de 10 pol. (720 x 1280 mdpi, 800 x 1280 mdpi etc).

A Figura 4 fornece uma visão mais detalhada de como diferentes larguras de tela em dp correspondem a diferentes tamanhos e orientações de tela.

Figura 4. Pontos de interrupção de largura recomendados para compatibilidade com diferentes tamanhos de tela.

Todos os valores para o qualificador de menor largura estão em pixels de densidade independente, porque o importante é a quantidade de espaço disponível na tela depois que o sistema considera a densidade do pixel, e não a resolução bruta de pixels.

Usar o qualificador de largura disponível

Em vez de alterar o layout com base na menor largura da tela, é possível alterá-lo com base na largura ou altura atualmente disponível. Por exemplo, se você tem um layout de dois painéis, pode querer usá-lo sempre que a tela fornecer pelo menos 600 dp de largura, o que pode mudar dependendo da orientação do dispositivo (paisagem ou retrato). Nesse caso, use o qualificador "available width" da seguinte forma:

    res/layout/main_activity.xml         # For handsets (smaller than 600dp available width)
    res/layout-w600dp/main_activity.xml  # For 7” tablets or any screen with 600dp
                                         #   available width (possibly landscape handsets)
    

Se a altura disponível for uma preocupação, você poderá fazer o mesmo usando o qualificador "altura disponível". Por exemplo, layout-h600dp para telas com pelo menos 600 dp de altura.

Adicionar qualificadores de orientação

Embora seja possível oferecer compatibilidade com todas as variações de tamanho usando apenas combinações dos qualificadores "menor largura" e "largura disponível", você também pode querer mudar a experiência do usuário quando ele alternar entre as orientações de retrato e paisagem.

Para isso, adicione o qualificador port ou land aos nomes do diretório de recursos. Esses qualificadores precisam ser posicionados depois dos outros qualificadores de tamanho. Exemplo:

    res/layout/main_activity.xml                # For handsets
    res/layout-land/main_activity.xml           # For handsets in landscape
    res/layout-sw600dp/main_activity.xml        # For 7” tablets
    res/layout-sw600dp-land/main_activity.xml   # For 7” tablets in landscape
    

Para mais informações sobre todos os qualificadores de configuração de tela, consulte a tabela 2 no guia Fornecimento de recursos.

Modularizar componentes de IU com fragmentos

Ao criar seu app para vários tamanhos de tela, verifique se você não está duplicando desnecessariamente o comportamento da IU nas suas atividades. Portanto, você precisa usar fragmentos para extrair a lógica da sua IU em componentes diferentes. Em seguida, você pode combinar fragmentos para criar layouts de vários painéis ao executá-los em uma tela grande ou colocá-los em atividades separadas ao executar o app em um celular.

Por exemplo, um app de notícias em um tablet pode exibir uma lista de artigos no lado esquerdo e um artigo completo no lado direito, com a seleção de um artigo à esquerda atualizando a visualização à direita. No entanto, em um celular, esses dois componentes precisam aparecer em telas separadas, considerando que selecionar um artigo de uma lista muda toda a tela para mostrá-lo.

Para saber mais, consulte Como criar uma IU dinâmica com fragmentos.

Oferecer compatibilidade com o Android 3.1 com qualificadores de tamanho legados

Se seu app for compatível com o Android 3.1 (API de nível 12) ou anterior, você precisará usar os qualificadores de tamanho legados além dos qualificadores "menor largura/largura disponível" descritos acima.

No exemplo acima, se você quiser um layout de dois painéis em dispositivos maiores, precisará usar o qualificador de configuração "large" para oferecer compatibilidade com a versão 3.1 e anteriores. Portanto, para implementar esses layouts nessas versões mais antigas, você pode ter estes arquivos:

    res/layout/main_activity.xml           # For handsets (smaller than 640dp x 480dp)
    res/layout-large/main_activity.xml     # For small tablets (640dp x 480dp and bigger)
    res/layout-xlarge/main_activity.xml    # For large tablets (960dp x 720dp and bigger)
    

Usar aliases de layout

Ao oferecer compatibilidade com versões anteriores e posteriores ao Android 3.2, você precisa usar os qualificadores "menor largura" e "grande" nos seus layouts. Por isso, é necessário um arquivo chamado res/layout-large/main.xml, que pode ser idêntico a res/layout-sw600dp/main.xml.

Para evitar essa duplicação do mesmo arquivo, você pode usar arquivos aliases. Por exemplo, você pode definir os seguintes layouts:

    res/layout/main.xml            # single-pane layout
    res/layout/main_twopanes.xml   # two-pane layout
    

E adicionar estes dois arquivos:

  • res/values-large/layout.xml:
        <resources>
            <item name="main" type="layout">@layout/main_twopanes</item>
        </resources>
        
  • res/values-sw600dp/layout.xml:
        <resources>
            <item name="main" type="layout">@layout/main_twopanes</item>
        </resources>
        

O conteúdo desses dois arquivos é idêntico, mas eles não definem realmente o layout. Eles apenas configuram main para ser um alias de main_twopanes. Como esses arquivos têm seletores large e sw600dp, eles se aplicam a telas grandes, independentemente da versão do Android. TVs e tablets anteriores à versão 3.2 correspondem a large, enquanto os de versões mais recentes correspondem a sw600dp.

Criar bitmaps nine-patch esticáveis

Se você usar um bitmap como plano de fundo em uma visualização que muda de tamanho, perceberá que o Android dimensiona suas imagens conforme a visualização aumenta ou diminui, com base no tamanho da tela ou do conteúdo da visualização. Isso geralmente leva a um desfoque visível ou outros artefatos de dimensionamento. A solução é usar bitmaps nine-patch, que são arquivos PNG especialmente formatados que indicam as áreas que não podem ser esticadas.

Um bitmap nine-patch é basicamente um arquivo PNG padrão, mas com uma borda extra de 1 px que indica quais pixels serão esticados (e com uma extensão .9.png em vez de apenas .png). Como mostrado na Figura 5, a interseção entre as linhas pretas na borda esquerda e na borda superior é a área do bitmap que pode ser esticada.

Outra opção é definir a região segura em que o conteúdo precisa entrar na visualização adicionando linhas nas bordas direita e inferior.

Figura 5. Uma imagem nine-patch (button.9.png).

Quando você aplica um nine-patch como plano de fundo em uma visualização, o framework estica a imagem corretamente para acomodar o tamanho do botão.

Se precisar de ajuda para criar uma imagem nine-patch com um bitmap, consulte Criar bitmaps redimensionáveis.

Testar em todos os tamanhos de tela

É importante testar seu app em vários tamanhos de tela para poder garantir que sua IU seja dimensionada corretamente. Se você não tem acesso a dispositivos físicos para todos os diferentes tamanhos de tela, pode usar o Android Emulator para emular qualquer tamanho de tela.

Caso você prefira testar em um dispositivo físico, mas não queira comprar dispositivos, use o Firebase Test Lab para acessar dispositivos em um data center do Google.

Declarar compatibilidade com tamanho de tela específico

Se você não quiser que o app seja executado em alguns tamanhos de tela, pode definir limites de até quanto sua tela pode ser redimensionada ou até mesmo limitar quais dispositivos podem instalar o app com base na configuração de tela. Para saber mais, consulte Declaração de suporte restrito à tela.