Compatibilidade com dobráveis triplos e na horizontal

Um dispositivo dobrável no modo paisagem nas posições fechada e totalmente aberta ao lado de um dispositivo triplo nas posições fechada e totalmente aberta.

Os desenvolvedores costumam encontrar dificuldades exclusivas ao criar aplicativos para dispositivos dobráveis, especialmente aparelhos como o Samsung Trifold ou o Pixel Fold original, que abre no formato paisagem (rotation_0 = landscape). Os erros dos desenvolvedores incluem:

  • Suposições incorretas sobre a orientação do dispositivo
  • Casos de uso ignorados
  • Falha ao recalcular ou armazenar em cache valores em mudanças de configuração

Problemas específicos relacionados ao dispositivo incluem:

  • Uma incompatibilidade na orientação natural do dispositivo entre as telas de capa e interna (suposições baseadas em rotation_0 = retrato), fazendo com que os apps falhem em trajetos de dobrar e desdobrar
  • Densidades de tela diferentes e tratamento incorreto da mudança de configuração density
  • Problemas de visualização da câmera causados pela dependência do sensor da câmera na orientação natural

Para oferecer uma experiência do usuário de alta qualidade em dispositivos dobráveis, concentre-se nas seguintes áreas críticas:

  • Determine a orientação do app com base na área de tela real que ele ocupa, não na orientação física do dispositivo
  • Atualize as visualizações da câmera para gerenciar a orientação e as proporções do dispositivo corretamente, evitar visualizações laterais e impedir imagens esticadas ou cortadas
  • Mantenha a continuidade do app durante a dobra ou desdobramento do dispositivo, retendo o estado com ViewModel ou abordagens semelhantes, ou processando manualmente as mudanças de densidade e orientação da tela, o que evita reinicializações ou perda de estado do app
  • Para apps que usam sensores de movimento, ajuste o sistema de coordenadas para se alinhar à orientação atual da tela e evite suposições baseadas em rotation_0 = retrato, garantindo interações precisas do usuário

Criar apps adaptáveis

Se o app já for adaptável e aderir ao nível otimizado (nível 2) descrito nas Diretrizes de qualidade de apps adaptáveis, ele vai funcionar bem em dispositivos dobráveis. Caso contrário, antes de verificar os detalhes específicos dos dispositivos dobráveis triplos e de paisagem, revise os seguintes conceitos básicos de desenvolvimento adaptável do Android.

Layouts adaptáveis

A interface precisa processar não apenas tamanhos de tela diferentes, mas também mudanças em tempo real na proporção, como desdobramento e entrada em modos de várias janelas ou modo janela para computador. Consulte Sobre layouts adaptáveis para mais orientações sobre como:

  • Projetar e implementar layouts adaptáveis
  • Ajustar a navegação principal do app com base no tamanho da janela
  • Usar classes de tamanho de janela para adaptar a interface do app
  • Simplificar a implementação de layouts canônicos, como lista-detalhe, usando as APIs do Jetpack
Um app com efeito letterbox em um dispositivo dobrável aberto e o mesmo app em tela cheia com um layout adaptável em outro dispositivo dobrável aberto.
Figura 1. Diferença entre layouts não adaptáveis (com efeito letterbox) e adaptáveis.

Classes de tamanho de janela

Dispositivos dobráveis, incluindo dobráveis de paisagem e triplos, podem mudar instantaneamente entre classes de tamanho de janela compactas, médias e expandidas. Entender e implementar essas classes garante que o app mostre os componentes de navegação e a densidade de conteúdo corretos para o estado atual do dispositivo.

Representação de um app em dispositivos dimensionados para as classes de tamanho de janela compacta, média e expandida.
Figura 2. Classes de tamanho de janela.

O exemplo a seguir usa a biblioteca adaptável do Material 3 para determinar quanto espaço o app tem disponível. Primeiro, ele invoca a currentWindowAdaptiveInfo() função e, em seguida, usa os layouts correspondentes para as três classes de tamanho de janela:

val adaptiveInfo = currentWindowAdaptiveInfo()
val windowSizeClass = adaptiveInfo.windowSizeClass

when {
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Expanded
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
  else -> // Compact
}

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

Qualidade de apps adaptáveis

Aderir ao nível 2 (adaptável otimizado) ou nível 1 (adaptável diferenciado) das Diretrizes de qualidade de apps adaptáveis garante que o app ofereça uma experiência do usuário interessante em dispositivos triplos, dobráveis de paisagem, e outros dispositivos de tela grande. As diretrizes abrangem verificações críticas em vários níveis para passar de um app adaptável pronto para uma experiência diferenciada.

Android 16 e versões mais recentes

Para apps direcionados ao Android 16 (nível 36 da API) e versões mais recentes, o sistema ignora restrições de orientação, redimensionamento e proporção em telas com largura mínima >= 600 dp. Os apps preenchem toda a janela de exibição, independente de proporção ou da orientação preferida do usuário, e o modo de compatibilidade com efeito letterbox não é mais usado.

Considerações especiais

Os dispositivos dobráveis triplos e de paisagem introduzem comportamentos de hardware exclusivos que exigem tratamento específico, principalmente em relação a sensores, visualização da câmera e continuidade da configuração (retenção de estado ao dobrar, desdobrar ou redimensionar).

Visualização da câmera

Um problema comum em dispositivos dobráveis de paisagem ou cálculos de proporção (em cenários como Várias janelas, modo janela para computador ou telas conectadas) é quando a visualização da câmera aparece esticada, de lado, cortada ou girada.

Suposições incompatíveis

Esse problema geralmente acontece em dispositivos de tela grande e dobráveis porque os apps podem presumir relações fixas entre recursos da câmera, como proporção e orientação do sensor, e recursos do dispositivo, como orientação e orientação natural.

Novos formatos desafiam essa suposição. Um dispositivo dobrável pode mudar o tamanho de exibição e a proporção da tela sem que a rotação do dispositivo mude. Por exemplo, desdobrar um dispositivo muda a proporção, mas, se o usuário não girar o dispositivo, a rotação dele permanecerá a mesma. Se um app presumir que a proporção está relacionada à rotação do dispositivo, ele poderá girar ou dimensionar incorretamente a visualização da câmera. O mesmo pode acontecer se um app presumir que a orientação do sensor da câmera corresponde a uma orientação de dispositivo retrato, o que nem sempre é verdade para dispositivos dobráveis de paisagem.

Solução 1: Jetpack CameraX (melhor)

A solução mais simples e robusta é usar a biblioteca Jetpack CameraX. O elemento da interface PreviewView foi projetado para processar automaticamente todas as complexidades de visualização:

  • PreviewView se ajusta corretamente à orientação do sensor, à rotação do dispositivo e ao dimensionamento.
  • Ele mantém a proporção da imagem da câmera, geralmente centralizando e cortando (FILL_CENTER).
  • Você pode definir o tipo de escala como FIT_CENTER para aplicar o efeito letterbox à visualização, se necessário.

Para mais informações, consulte Implementar uma visualização na documentação do CameraX.

Solução 2: CameraViewfinder

Se você estiver usando uma base de código Camera2 atual, a biblioteca CameraViewfinder (compatível com versões anteriores ao nível 21 da API) será outra solução moderna. Ela simplifica a exibição da transmissão da câmera usando um TextureView ou SurfaceView e aplicando todas as transformações necessárias (proporção, escala e rotação) para você.

Para mais informações, consulte a postagem do blog Apresentação do visor da câmera e Visualização da câmera o guia do desenvolvedor.

Solução 3: implementação manual do Camera2

Se você não puder usar o CameraX ou o CameraViewfinder, calcule manualmente a orientação e a proporção e garanta que os cálculos sejam atualizados em cada mudança de configuração:

  • Receba a orientação do sensor da câmera (por exemplo, 0, 90, 180, 270 graus) de CameraCharacteristics.
  • Receba a rotação atual da tela do dispositivo (por exemplo, 0, 90, 180, 270 graus).
  • Use esses dois valores para determinar as transformações necessárias para seu SurfaceView ou TextureView.
  • Garanta que a proporção da saída Surface corresponda à proporção da visualização da câmera para evitar distorção.
  • O app de câmera pode estar em execução em uma parte da tela, no modo de várias janelas ou modo janela para computador ou em uma tela conectada. Por esse motivo, o tamanho da tela não deve ser usado para determinar as dimensões do visor da câmera. Use as métricas da janela.

Para mais informações, consulte o Guia do desenvolvedor de visualização da câmera e o vídeo Seu app de câmera em diferentes formatos.

Solução 4: realizar ações básicas da câmera usando uma intent

Se você não precisar de muitos recursos da câmera, uma solução simples é realizar ações básicas da câmera, como capturar uma foto ou um vídeo usando o app de câmera padrão do dispositivo. Não é necessário fazer a integração com uma biblioteca de câmera. Em vez disso, use uma intent.

Para mais informações, consulte Intents de câmera.

Configuração e continuidade

Dispositivos dobráveis aprimoram a versatilidade da interface, mas podem iniciar mais mudanças de configuração do que os não dobráveis. O app precisa gerenciar essas mudanças de configuração e as combinações delas, como rotação, dobra/desdobramento e redimensionamento de janela em modos de várias janelas ou de computador, mantendo ou restaurando o estado do app. Por exemplo, os apps precisam manter a seguinte continuidade:

  • Estado do app sem falhas ou mudanças disruptivas para os usuários (por exemplo, ao trocar de tela ou enviar o app para segundo plano)
  • Posição de rolagem dos campos roláveis
  • Texto digitado em campos de texto e estado do teclado
  • Posição de reprodução de mídia para que a reprodução seja retomada de onde parou quando a mudança de configuração foi iniciada

As mudanças de configuração que são acionadas com frequência incluem screenSize, smallestScreenSize, screenLayout, orientation, density, fontScale, touchscreen e keyboard.

Consulte android:configChanges e Gerenciar mudanças de configuração. Para mais informações sobre como gerenciar o estado do app, consulte Salvar estados da interface.

Mudanças de configuração de densidade

As telas externa e interna de dispositivos dobráveis triplos e de paisagem podem apresentar densidades de pixels diferentes. Portanto, o gerenciamento da mudança de configuração para density requer atenção extra. O Android normalmente reinicia a atividade quando a densidade de exibição muda, o que pode causar perda de dados. Para impedir que o sistema reinicie a atividade, declare o tratamento de densidade no manifesto e gerencie a mudança de configuração de maneira programática no app.

Configuração do AndroidManifest.xml

  • density: declara que o app vai processar a mudança de densidade da tela
  • Outras mudanças de configuração: também é recomendável declarar outras mudanças de configuração que ocorrem com frequência, por exemplo, screenSize, orientation, keyboardHidden, fontScale e assim por diante

Declarar a densidade (e outras mudanças de configuração) impede que o sistema reinicie a atividade e, em vez disso, chama onConfigurationChanged().

Implementação de onConfigurationChanged()

Quando ocorre uma mudança de densidade, é necessário atualizar os recursos (como recarregar bitmaps ou recalcular tamanhos de layout) no callback:

  • Verifique se o DPI foi alterado para newConfig.densityDpi
  • Redefina visualizações personalizadas, drawables personalizados e assim por diante para a nova densidade

Itens de recursos a serem processados

  • Recurso de imagem: substitua bitmaps e drawables por recursos específicos de densidade ou ajuste a escala diretamente
  • Unidade de layout (conversão de dp para px): recalcule o tamanho da visualização, a margem, preenchimento
  • Tamanho da fonte e do texto: reaplique o tamanho do texto da unidade sp
  • Desenho View/Canvas personalizado: atualize os valores baseados em pixels usados para desenhar Canvas

Determinar a orientação do app

Nunca confie na rotação do dispositivo físico ao criar apps adaptáveis, porque ela será ignorada em dispositivos de tela grande e um app no modo de várias janelas poderá ter uma orientação diferente do dispositivo. Em vez disso, use Configuration.orientation ou WindowMetrics para identificar se o app está no momento na orientação paisagem ou retrato com base no tamanho da janela.

Solução 1: usar Configuration.orientation

Essa propriedade identifica a orientação em que o app está sendo exibido no momento.

Solução 2: usar WindowMetrics#getBounds()

Você pode acessar os limites de exibição atuais do app e verificar a largura e a altura dele para determinar a orientação.

Se você precisar limitar a orientação do app em smartphones (ou nas telas externas de dispositivos dobráveis), mas não em dispositivos de tela grande, consulte Restringir a orientação do app em smartphones.

Posições e modos de exibição

As posições e estados dobráveis, como mesa e HALF_OPENED são compatíveis com dispositivos dobráveis de retrato e paisagem. No entanto, os dispositivos dobráveis triplos não oferecem suporte à posição de mesa e não podem ser usados HALF_OPENED. Em vez disso, os dispositivos dobráveis triplos oferecem uma tela maior para uma experiência do usuário exclusiva quando totalmente desdobrados.

Para diferenciar seu app em dispositivos dobráveis que oferecem suporte a HALF_OPENED, use Jetpack WindowManager APIs, como FoldingFeature.

Saiba mais sobre posições, estados e suporte para visualização da câmera em dispositivos dobráveis nos seguintes guias do desenvolvedor:

Dispositivos dobráveis oferecem experiências de visualização únicas. O modo de tela traseira e o modo de tela dupla permitem criar recursos especiais de exibição para dispositivos dobráveis, como a prévia da selfie de câmera traseira e telas interna e externa simultâneas. Para mais informações, consulte:

Como bloquear a orientação para a orientação natural do sensor

Para casos de uso muito específicos, em particular, apps que precisam assumir a tela inteira sem relação com o estado dobrado do dispositivo, a flag nosensor permite bloquear o app na orientação natural do dispositivo. Por exemplo, em um Pixel Fold, a orientação natural do dispositivo quando dobrado é retrato, enquanto a orientação natural quando desdobrado é paisagem. Adicionar a flag nosensor força o app a ser bloqueado no modo retrato quando executado na tela externa e bloqueado no modo paisagem quando executado no display interno.

<activity
  android:name=".MainActivity"
  android:screenOrientation="nosensor">

Remapeamento de sensores de jogos e XR

Para jogos e apps de XR, os dados brutos do sensor (como giroscópio ou acelerômetro) são fornecidos no sistema de coordenadas fixo do dispositivo. Se o usuário girar o dispositivo para jogar um jogo no modo paisagem, os eixos do sensor não vão girar com a tela, levando a controles de jogo incorretos.

Para corrigir esse problema, verifique o Display.getRotation() atual e remapeie os eixos de acordo:

  • Rotação 0: x=x, y=y
  • Rotação 90: x=-y, y=x
  • Rotação 180: x=-x, y=-y
  • Rotação 270: x=y, y=-x

Para vetores de rotação (usados em apps de bússola ou XR), use SensorManager.remapCoordinateSystem() para mapear a direção da lente da câmera ou a parte de cima da tela para os novos eixos com base na rotação atual.

Compatibilidade de apps

Os aplicativos precisam seguir as diretrizes de qualidade de apps para garantir a compatibilidade em todos os formatos e telas conectadas. Se um aplicativo não puder seguir as diretrizes, os fabricantes de dispositivos poderão implementar tratamentos de compatibilidade, embora isso possa degradar a experiência do usuário.

Para mais informações, consulte a lista abrangente de soluções alternativas de compatibilidade fornecidas na plataforma, especificamente aquelas relacionadas à visualização da câmera, substituições e mudanças na API do Android 16 que podem mudar o comportamento do app.

Para saber mais sobre como criar apps adaptáveis, consulte as Diretrizes de qualidade de apps adaptáveis.