Design responsivo/adaptável com visualizações

Testar o Compose
O Jetpack Compose é o kit de ferramentas de interface recomendado para Android. Aprenda a trabalhar com layouts responsivos no Compose.

Os layouts responsivos/adaptáveis proporcionam uma experiência do usuário otimizada, independente do tamanho da tela. Implemente layouts responsivos/adaptáveis para permitir que o app baseado em visualização ofereça suporte a todos os tamanhos, orientações e configurações de tela, incluindo configurações redimensionáveis, como o modo de várias janelas.

Design responsivo

A primeira etapa para oferecer suporte a vários formatos de dispositivo é criar um layout que responda a variações na quantidade de espaço de exibição disponível para o app.

ConstraintLayout

A melhor maneira de criar um layout responsivo é usar ConstraintLayout como o layout básico da interface. O 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. Todas as visualizações podem se mover e ser redimensionadas ao mesmo tempo, conforme o espaço de exibição muda.

A maneira mais fácil de criar um layout com o ConstraintLayout é usar o Layout Editor no Android Studio. O Layout Editor permite que você arraste novas visualizações para o layout, aplique restrições relativas a visualizações mãe e irmãs e defina propriedades de visualização, tudo isso sem editar nenhum XML manualmente.

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

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

Largura e altura responsivas

Para garantir que o layout seja responsivo a diferentes tamanhos de tela, use wrap_content, match_parent ou 0dp (match constraint) para a largura e a altura dos componentes de visualização em vez de valores codificados:

  • wrap_content: a visualização define o tamanho para ajustar o conteúdo que ela contém.
  • match_parent: a visualização se expande o máximo possível dentro da visualização mãe.
  • 0dp (match constraint): em um ConstraintLayout, é semelhante a match_parent. A visualização ocupa todo o espaço disponível dentro das restrições dela.

Exemplo:

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

A Figura 4 mostra como a largura e a altura da TextView se ajustam conforme a largura da tela muda pela orientação do dispositivo.

Figura 4. Uma TextView responsiva.

A TextView define a largura para preencher todo o espaço disponível (match_parent) e a altura exatamente como o espaço necessário para a altura do texto (wrap_content). Isso permite que a visualização se adapte a diferentes dimensões de exibição e a diferentes quantidades de texto.

Se você estiver usando um LinearLayout, também poderá expandir as visualizações filhas com base no peso do layout para que elas sejam preenchidas proporcionalmente no espaço disponível. 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.

O ConstraintLayout pode criar quase todos os layouts possíveis com LinearLayout sem impacto no desempenho. Por isso, converta seu LinearLayout aninhado em ConstraintLayout. Em seguida, você pode definir layouts ponderados com cadeias de restrição.

Design adaptável

O layout do app precisa ser sempre responsivo a diferentes tamanhos de tela. No entanto, até mesmo um layout responsivo não oferece a melhor experiência do usuário em todos os dispositivos ou telas do modo de várias janelas. Por exemplo, a IU projetada para um smartphone provavelmente não oferece uma experiência ideal em um tablet. O design adaptável fornece layouts alternativos otimizados para diferentes dimensões de tela.

SlidingPaneLayout para interfaces de detalhes e listas

Uma interface de detalhes e listas normalmente oferece uma experiência do usuário diferente em telas de tamanhos variados. Em telas grandes, os painéis de lista e de detalhes costumam estar lado a lado. Quando um item da lista é selecionado, as informações do item são mostradas no painel de detalhes sem alterar a interface. Os dois painéis permanecem lado a lado. No entanto, em telas pequenas, os dois painéis são mostrados separadamente, cada um ocupando toda a área de exibição. Quando um item no painel da lista é selecionado, o painel de detalhes (que contém as informações do item selecionado) substitui o painel da lista. A navegação de retorno substitui o painel de detalhes pela lista.

O SlidingPaneLayout gerencia a lógica para determinar qual das duas experiências do usuário é adequada para o tamanho atual da janela:

<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/item_navigation" />

</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Os atributos layout_width e layout_weight das duas visualizações contidas em SlidingPaneLayout determinam o comportamento SlidingPaneLayout. No exemplo, se a janela for grande o suficiente (pelo menos 580 dp de largura) para mostrar as duas visualizações, os painéis vão ser exibidos lado a lado. No entanto, se a largura da janela for menor que 580 dp, os painéis vão ser exibidos individualmente em relação aos outros para ocupar toda a janela do app.

Se a largura da janela for maior que a largura mínima especificada (580 dp), os valores layout_weight poderão ser usados para dimensionar os dois painéis proporcionalmente. No exemplo, o painel de lista sempre tem 280 dp de largura porque não tem um peso. No entanto, o painel de detalhes sempre preenche qualquer espaço horizontal além de 580 dp devido à configuração layout_weight da visualização.

Recursos de layouts alternativos

Para adaptar o design da interface a vários tamanhos de tela, use layouts alternativos identificados por qualificadores de recursos.

Figura 5. O mesmo app usando layouts diferentes para tamanhos de tela diferentes.

Você pode criar outros diretórios res/layout/ no código-fonte do app a fim de fornecer layouts adaptáveis específicos para a tela. Crie um diretório para cada configuração de tela que exige um layout diferente. Em seguida, anexe um qualificador de configuração de tela ao nome do diretório layout. Por exemplo, layout-w600dp para telas com 600 dp de largura disponível.

Os qualificadores de configuração representam o espaço de exibição visível disponível para a interface do app. O sistema considera todas as decorações do sistema, como a barra de navegação, e mudanças na configuração de janelas, como o modo de várias janelas, ao selecionar o layout do app.

Para criar layouts alternativos no Android Studio, consulte Usar variantes de layout para otimizar para diferentes telas em Desenvolver uma interface com Views.

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).

Ao descrever o tamanho da tela como uma medida de dp, o Android permite que você crie layouts voltados a dimensões de tela específicas sem se preocupar com diferentes densidades de pixel.

Por exemplo, é possível criar um layout com o nome main_activity, otimizado para celulares e tablets, criando versões diferentes do arquivo em diferentes diretórios:

res/layout/main_activity.xml           # For phones (smaller than 600dp smallest width)
res/layout-sw600dp/main_activity.xml   # For 7" tablets (600dp wide or wider)

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

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

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

A figura a seguir mostra uma visão mais detalhada de como diferentes larguras de tela em dp correspondem a diferentes tamanhos e orientações de tela.

Figura 6. Pontos de interrupção de largura recomendados para oferecer suporte a tamanhos diferentes de tela.

Os valores do qualificador de menor largura são medidos em dp, porque o importante é a quantidade de espaço de exibição disponível depois que o sistema considera a densidade de pixels, e não a resolução bruta deles.

Os tamanhos especificados usando qualificadores de recursos, como a menor largura, não são tamanhos reais de tela. Na verdade, eles especificam a largura ou a altura em unidades de dp que estão disponíveis para a janela do app. O sistema Android pode usar parte da tela para a interface do sistema (por exemplo, a barra de sistema na parte de baixo da tela ou a barra de status na parte de cima). Portanto, a tela pode não estar totalmente disponível para o layout. Se o app for usado no modo de várias janelas, ele só terá acesso ao tamanho da janela que o contém. Quando a janela é redimensionada, ela aciona uma mudança de configuração com o novo tamanho da janela, permitindo que o sistema selecione um arquivo de layout adequado. Assim, os tamanhos dos qualificadores de recurso declarados precisam especificar somente o espaço necessário para o app. O sistema considera todo o espaço usado pela IU do sistema ao fornecer espaço para o layout.

Qualificador de largura disponível

Em vez de mudar o layout com base na menor largura da tela, é possível mudá-lo com base na largura ou altura disponível. Por exemplo, você pode usar um layout de dois painéis sempre que a tela oferecer pelo menos 600 dp de largura, o que pode mudar dependendo da orientação do dispositivo (paisagem ou retrato). Nesse caso, use o qualificador de largura disponível desta maneira:

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

Se a altura disponível for uma preocupação para o app, você pode usar o qualificador altura disponível. Por exemplo, layout-h600dp para telas com pelo menos 600 dp de altura.

Qualificadores de orientação

Embora seja possível oferecer suporte a todas as variações de tamanho usando apenas combinações dos qualificadores de 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 layout. Confira se os qualificadores de orientação vêm depois dos qualificadores de tamanho. Exemplo:

res/layout/main_activity.xml                # For phones
res/layout-land/main_activity.xml           # For phones 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 Visão geral dos recursos do app.

Classes de tamanho de janela

As classes de tamanho de janela são pontos de interrupção da janela de visualização que ajudam a criar layouts adaptáveis. Os pontos de interrupção identificam a área de exibição disponível para o app como compacta, média ou expandida. A largura e a altura são especificadas separadamente, para que o app sempre tenha uma classe de tamanho de janela para largura e outra para altura.

Para aplicar layouts adaptáveis de forma programática, faça o seguinte:

  • Criar recursos de layout com base nos pontos de interrupção de classes de tamanho da janela
  • Calcule as classes de tamanho de janela de largura e altura do app usando a função WindowSizeClass#compute() da biblioteca Jetpack WindowManager.
  • Inflar o recurso de layout para as classes de tamanho de janela atuais

Para mais informações, consulte Classes de tamanho de janela.

Componentes de interface modularizados usando fragmentos

Ao criar o app para vários tamanhos de tela, use fragmentos para extrair a lógica da IU em componentes diferentes e garantir que não há duplicação desnecessária do comportamento da IU nas atividades. Depois, você pode combinar fragmentos para criar layouts de vários painéis em telas grandes ou colocar fragmentos em atividades separadas em telas pequenas.

Por exemplo, o padrão de detalhes e listas (consulte SlidingPaneLayout acima) pode ser implementado com um fragmento que contém a lista e outro que contém os detalhes do item da lista. Em telas grandes, os fragmentos podem ser mostrados lado a lado. Em telas pequenas, podem aparecer individualmente, preenchendo a tela.

Para saber mais, consulte a visão geral de fragmentos.

Incorporação de atividades

Se o app for composto de várias atividades, a incorporação de atividades vai permitir que você crie uma IU adaptável com facilidade.

Esse recurso permite mostrar várias atividades ou instâncias da mesma atividade simultaneamente na janela de tarefas de um app. Em telas grandes, as atividades podem ser mostradas lado a lado. Em telas pequenas, elas podem ser empilhadas uma sobre a outra.

Para determinar como o app exibe as atividades, crie um arquivo de configuração XML que o sistema vai usar para determinar a apresentação adequada com base no tamanho da tela. Como alternativa, você pode fazer chamadas da API WindowManager do Jetpack.

A incorporação de atividades oferece suporte a mudanças de orientação do dispositivo e dispositivos dobráveis, empilhando e desempilhando atividades conforme o dispositivo é girado ou dobrado e desdobrado.

Para mais informações, consulte Incorporação de atividades.

Tamanhos e proporções de tela

Teste o app em vários tamanhos e proporções de tela para garantir que a IU seja dimensionada corretamente.

O Android 10 (nível 29 da API) e versões mais recentes oferecem suporte a várias proporções. Os formatos dobráveis podem variar de telas altas e estreitas, como 21:9 quando dobrado, até uma proporção quadrada de 1:1 quando desdobrado.

Para garantir a compatibilidade com o maior número possível de dispositivos, teste seus apps com o maior número possível de proporções de tela:

Figura 7. Várias proporções de tela.

Se você não tiver acesso a dispositivos para todos os diferentes tamanhos de tela que quer testar, use o Android Emulator para emular quase qualquer tamanho de tela.

Se você preferir testar em um dispositivo real, mas não tiver um, use o Firebase Test Lab para acessar dispositivos em um data center do Google.

Outros recursos