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 seu app para diferentes tamanhos de tela garante que ele possa lidar com alterações 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 Android. Você precisa realizar outras etapas para que ele seja compatível com dispositivos Android Wear, TV, Auto e Chrome OS.

Para orientações de design para a criação de interface do usuário para diferentes telas, consulte as orientações de Material Design para uma IU responsiva.

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 o ConstraintLayout

A melhor forma de criar um layout responsivo para diferentes tamanhos de tela é usar o ConstraintLayout como layout de base na sua IU. O ConstraintLayout permite especificar a posição e o tamanho para 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 esticar juntas conforme o tamanho da tela muda.

A forma mais fácil de criar um layout com o ConstraintLayout é usar o Editor de layout do Android Studio. Ele permite que você arraste novas visualizações para o layout, anexe as limitações da visualização pai 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 Editor de layout 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 o RecyclerView. Mas, independentemente do layout usado, você precisa sempre evitar codificar 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 tamanho para o que for necessário para ajustar o conteúdo a essa visualização.

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

Por exemplo:

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

Embora o layout real dessa visualização dependa de outros atributos da visualização pai e de outras 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 com "match_parent" se ajusta conforme a largura da tela é alterada pela orientação do dispositivo.

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

Se você estiver usando um LinearLayout, também pode expandir as visualizações filhas com a ponderação do layout para que cada visualização preencha o espaço restante proporcional ao valor de ponderação. No entanto, para usar ponderações em um LinearLayout aninhado, é necessário que o sistema realize múltiplas passagens de layout para determinar o tamanho de cada visualização, diminuindo a velocidade do desempenho da sua IU. Felizmente, o ConstraintLayout pode alcançar quase todos os layouts possíveis com LinearLayout sem impactos no desempenho. Por isso, tente converter seu layout para ConstraintLayout. Em seguida, é possível definir layouts ponderados com cadeias de limitaçã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 ao usuário para todo tamanho 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

É possível 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 qualquer decoração do sistema (como a barra de navegação) e alterações 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 posterior), 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 você terminar de adicionar qualificadores, clique em OK. Consulte as seções a seguir para informações sobre os qualificadores de tamanho de tela.

Isso cria um arquivo de layout duplicado no diretório de layout 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 que evita quaisquer preocupações que você possa ter sobre diferentes densidades de pixel.

Por exemplo, você pode criar um layout chamado main_activity que seja 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, é 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. Limites de largura recomendados para compatibilidade com diferentes tamanhos de tela

Todos os valores para o qualificador de menor largura sã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 para você, você poderá fazer o mesmo usando o qualificador "available height". 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 "smallest width" e "available width", você pode também querer alterar a experiência do usuário quando ele alternar entre as orientações retrato e paisagem.

Para isso, é possível adicionar os qualificadores port e land aos nomes de diretórios de recursos. Certifique-se de que esses qualificadores sejam posicionados depois de outros qualificadores de tamanho. Por 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, certifique-se de que não está duplicando desnecessariamente o comportamento da IU em 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 altera 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 "smallest/available width" 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 "smallest-width" e "large" nos seus layouts. Portanto, você precisa de 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. Tablets e TVs anteriores ao 3.2 correspondem a large, e posteriores ao 3.2 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 precisam ser esticados e uma extensão .9.png, em vez de apenas .png. Conforme mostrado na figura 5, a intersecção entre as linhas pretas na esquerda e a borda superior é a área do bitmap que pode ser esticada.

Outra opção é possível 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, a estrutura de trabalho 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, pode usar 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 seu app seja executado em alguns tamanhos de tela, pode definir limites de até quanto sua tela pode ser redimensionada ou até limitar quais dispositivos podem instalar seu app, com base na configuração de tela. Para saber mais, consulte Declarar compatibilidade restrita a telas.