Os apps Android precisam oferecer suporte a um ecossistema de formatos de dispositivos em constante expansão. A interface de um app precisa ser responsiva para se adequar a uma grande variedade de tamanhos de tela, orientações diferentes e estados do dispositivo.
A IU responsiva se concentra nos princípios da flexibilidade e continuidade.
A flexibilidade se refere a layouts que fazem o uso ideal do espaço disponível e se ajustam quando esse espaço muda. Os ajustes podem fazer várias mudanças: aumentar o tamanho de uma única visualização, reposicionar as visualizações para que elas fiquem em locais mais acessíveis, mostrar ou ocultar outras visualizações ou uma combinação dessas opções.
Continuidade refere-se a uma experiência do usuário perfeita durante a transição de um tamanho de janela para outro. A experiência em que o usuário está envolvido precisa continuar sem interrupções. Como uma mudança de tamanho pode ser acompanhada por destruição e recriação de toda a hierarquia de visualização, é importante que o usuário não perca os dados dele nem a posição onde estava.
O que deve ser evitado
Evite usar valores físicos e de hardware para tomar decisões de layout. Pode ser tentador tomar decisões com base em um valor fixo, mas em muitas situações, esses valores não são úteis para determinar o espaço com que a interface pode trabalhar.
Os apps podem sofrer redimensionamento de janela ao serem executados no modo de várias janelas, ou janelas de forma livre, como o ChromeOS. Pode até haver mais de uma tela física, como um dispositivo dobrável ou um dispositivo com várias telas. Em todos esses casos, o tamanho físico da tela não é relevantes para decidir como exibir o conteúdo.
Pelo mesmo motivo, evite fixar o app em uma orientação ou proporção específica. Embora o dispositivo possa estar em uma orientação específica, seu app pode estar em uma orientação diferente com base apenas no tamanho da própria janela. Por exemplo, em um tablet no modo paisagem durante o uso do modo de várias janelas, um app pode estar em modo retrato porque é mais alto do que largo.
Além disso, evite determinar se o dispositivo é um smartphone ou tablet. O que se qualifica especificamente como um tablet é subjetivo, porque pode se basear em um determinado tamanho, proporção ou uma combinação de tamanho e proporção. Com o surgimento de novos formatos, essas suposições podem mudar facilmente, e essa distinção perde a importância.
Em vez de tentar qualquer uma das estratégias anteriores, use pontos de interrupção e classes de tamanho de janela.
Pontos de interrupção e classes de tamanho de janela
A parte real da tela alocada para o app é a janela do app. Ela pode ocupar a tela inteira ou parte dela; então considere o tamanho da janela ao tomar decisões importantes sobre o layout do app.
Ao projetar para vários formatos, encontre valores limite em que essas decisões importantes se ramificam em direções diferentes. Para isso, a grade de layout responsivo (link em inglês) do Material Design oferece pontos de interrupção para largura e altura, o que permite mapear tamanhos brutos em grupos discretos e padronizados chamados de classes de tamanho de janelas. Devido ao uso frequente de rolagem vertical, a maioria dos apps se preocupa principalmente com as classes de tamanho de largura. É possível otimizar a maioria dos aplicativos para todos os tamanhos de tela, lidando com apenas alguns pontos de interrupção. Para mais informações sobre classes de tamanho de janela, consulte Classes de tamanho de janela.
Elementos persistentes da IU
As diretrizes de layout do Material Design definem regiões para barras de apps, navegação e conteúdo. Normalmente, os dois primeiros são elementos de IU persistentes na raiz da hierarquia de visualização (ou muito próximos dela). "Permanente" não significa necessariamente que a visualização está sempre visível, mas que permanece no lugar enquanto outras visualizações de conteúdo podem ser movidas ou alteradas. Por exemplo, um elemento de navegação pode estar em uma gaveta deslizante que não está aberta, mas o ícone dela continua no mesmo lugar.
Os elementos permanentes podem ser responsivos e geralmente ocupam a largura total ou a altura total da janela. Portanto, prefira usar classes de tamanho para decidir onde colocá-los. Isso delimita o espaço restante para o conteúdo. No snippet abaixo, a atividade usa uma barra na parte de baixo para telas compactas e uma barra de apps na parte de cima para telas maiores. Os layouts qualificados usam pontos de interrupção de largura, conforme descrito anteriormente.
<!-- res/layout/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- content view(s) -->
<com.google.android.material.bottomappbar.BottomAppBar
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
... />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- res/layout-w600dp/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
... />
<!-- content view(s) -->
</androidx.constraintlayout.widget.ConstraintLayout>
Conteúdo
Após posicionar os elementos permanentes da IU, use o espaço restante
para o conteúdo, por exemplo, usando um NavHostFragment
com o gráfico de navegação
do seu app. Consulte
Navegação para IUs responsivas
para ver outras considerações.
Garantir que todos os dados estejam disponíveis para tamanhos diferentes
Atualmente, a maioria dos frameworks de apps usa um modelo de dados separado dos componentes do Android que contribuem para a IU (atividades, fragmentos e visualizações). Com o Jetpack, esse papel é normalmente realizado pelos ViewModels, que têm o benefício a mais de sobreviver às mudanças de configuração. Consulte Visão geral do ViewModel para mais informações.
Ao implementar um layout que se adapta a diferentes tamanhos, pode ser tentador usar um modelo de dados diferente com base no tamanho atual. No entanto, isso vai contra o princípio do fluxo de dados unidirecional. O fluxo de dados precisa ser reduzido para as visualizações, e eventos, como as interações do usuário, precisam ser distribuídos na parte de cima. A criação de uma dependência na outra direção, em que o modelo de dados depende da configuração da camada de IU, complica drasticamente isso. Quando o tamanho do app mudar, você vai precisar considerar converter um modelo de dados para outro.
Em vez disso, autorize que o modelo de dados acomode a maior classe de tamanho. Assim, você pode mostrar, ocultar ou reposicionar o conteúdo na IU para se adaptar à classe de tamanho atual. Veja abaixo algumas estratégias que você pode usar para decidir como o layout vai se comportar ao fazer a transição entre classes de tamanho.
Abrir conteúdo
Layouts canônicos (link em inglês): feed
O espaço expandido pode ser uma oportunidade de simplesmente aumentar o tamanho e reformatar o conteúdo para torná-lo mais acessível.
Aumente o tamanho das coleções. Muitos apps mostram uma coleção de itens em um
contêiner de rolagem, como RecyclerView
ou ScrollView
. Permitir que um
contêiner se torne automaticamente maior significa que é possível mostrar mais conteúdo.
No entanto, tenha cuidado para que o conteúdo dentro do contêiner não fique
muito esticado ou distorcido. Por exemplo, com uma RecyclerView
, considere
usar um gerenciador de layout diferente como
GridLayoutManager
,
StaggeredGridLayoutManager
ou
FlexboxLayout
(link em inglês), quando
a largura não for compacta.
Itens individuais também podem usar um tamanho ou uma forma diferente para mostrar mais conteúdo e distinguir os limites do item com mais facilidade.
Enfatize um elemento principal. Se o layout tiver um ponto focal específico, como uma imagem ou um vídeo, expanda o elemento quando a janela do app aumentar para manter a atenção do usuário nele. Outros elementos de apoio podem ser reorganizados em volta ou abaixo da visualização principal.
Há muitas maneiras de criar um layout assim, mas o uso de ConstraintLayout
é
especialmente adequado para essa finalidade, porque fornece muitas maneiras de
restringir o tamanho de uma visualização filha (como por porcentagem ou aplicação de uma
proporção) e de posicionar as filhas em relação a si próprias ou a
outras. Saiba mais sobre todos esses recursos em
Criar uma IU responsiva com o ConstraintLayout.
Mostrar conteúdo recolhível por padrão. Quando houver espaço disponível, exponha conteúdo que só seria acessado com interações a mais do usuário, como toques, rolagem ou gestos. Por exemplo, o conteúdo que aparece em uma interface com guias quando compacto pode ser reorganizado em colunas ou uma lista quando há mais espaço disponível.
Expandir margens. Se o espaço for muito grande e não for possível definir uma organização interessante mesmo após usar todos os itens, expanda as margens do layout para que o conteúdo permaneça centralizado e as visualizações individuais tenham tamanhos naturais e espaçamento entre elas.
Como alternativa, um componente de tela cheia pode se transformar em uma IU de caixa de diálogo flutuante. Isso se adequa especialmente bem quando esse componente exige foco exclusivo para atender a uma tarefa imediata do usuário, como escrever um e-mail ou criar um evento da agenda.
Adicionar conteúdo
Layouts canônicos (link em inglês): painel de suporte, visualização em detalhes da lista
Usar um painel de suporte. Um painel de suporte apresenta conteúdo extra ou ações contextuais relacionadas ao conteúdo principal, como comentários em um documento ou itens em uma playlist. Normalmente, eles usam um terço da parte de baixo da tela para a altura expandida ou um terço ao longo da borda à direita para a largura expandida.
É importante considerar onde colocar esse conteúdo quando não há espaço suficiente para mostrar o painel. Confira algumas alternativas a serem exploradas:
- Gaveta lateral ao longo da borda usando o
DrawerLayout
. - Gaveta de baixo usando o
BottomSheetBehavior
. - Menu ou janela pop-up acessível ao tocar em um ícone de menu.
Criar um layout de dois painéis. Telas grandes podem mostrar uma combinação de recursos que normalmente aparecem separadamente em telas menores. Um padrão de interação comum em muitos apps é mostrar uma lista de itens, como contatos ou resultados da pesquisa, e alternar para os detalhes de um item selecionado. Em vez de ampliar a lista para telas maiores, use a visualização de detalhes e listas para mostrar os dois recursos lado a lado em um layout de dois painéis. Diferente de um painel de suporte, o painel de visualização de detalhes e listas é um elemento que pode ser mostrado de forma independente em telas menores.
Use o widget dedicado
SlidingPaneLayout
para implementar uma visualização de detalhes e listas. Esse
widget calcula automaticamente se há espaço suficiente para mostrar ambos
os painéis com base no valor layout_width
especificado neles,
e qualquer espaço restante pode ser distribuído usando layout_weight
. Quando não
há espaço suficiente, cada painel usa a largura total do layout, e o
painel de detalhes desliza para fora da tela ou para a parte de cima do painel da lista.
O guia Criar um layout de dois painéis contém mais
detalhes sobre o uso do SlidingPaneLayout
. Esse padrão também pode
afetar a forma como você estrutura o gráfico de navegação. Consulte
Navegação para interfaces responsivas.
Outros recursos
- Material Design: Como aplicar o layout (link em inglês)
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Criar um layout de dois painéis
- Design responsivo/adaptável com visualizações
- Layouts canônicos para telas grandes