Orientação restrita do app em smartphones, mas não em telas grandes

Ícone de classificação de duas estrelas

Como o app funciona muito bem em smartphones na orientação retrato, você o restringiu apenas a esse modo. Mas você percebe uma oportunidade de melhorar o suporte do app em telas grandes na orientação paisagem.

Como você pode aproveitar o melhor de dois mundos, restringindo o app à orientação retrato em telas pequenas, mas ativando o modo paisagem em telas grandes?

Práticas recomendadas

Os melhores apps respeitam as preferências do usuário, como a orientação do dispositivo.

As diretrizes de qualidade de apps adaptáveis recomendam que os apps ofereçam suporte a todas as configurações de dispositivos, incluindo orientações de retrato e paisagem, modo de várias janelas e estados dobrados e desdobrados. Os apps precisam otimizar layouts e interfaces do usuário para diferentes configurações, além de salvar e restaurar o estado durante as mudanças de configuração.

Esta seção apresenta apenas uma medida temporária, oferecendo o mínimo de suporte para telas grandes. Use estas dicas até melhorar o app o suficiente para oferecer suporte total a todas as configurações de dispositivos.

Ingredientes

  • screenOrientation: configuração do manifesto do app que permite especificar como o aplicativo responde às mudanças de orientação do dispositivo.
  • Activity#setRequestedOrientation(): método com que é possível mudar a orientação do app no momento da execução.
  • LocalConfiguration: provedor local combinável que expõe o Configuration do dispositivo atual, permitindo que você leia as dimensões da tela em DPs.
  • LaunchedEffect: API de efeito colateral do Compose que executa um bloco de código quando uma chave muda (neste caso, quando a configuração muda).

Etapas

Ativa o app para processar mudanças de orientação por padrão no manifesto dele. Em seguida, no tempo de execução, use o Jetpack Compose para restringir dinamicamente a orientação para retrato em telas compactas (smartphones), permitindo todas as orientações em telas grandes.

1. Especificar a configuração de orientação no manifesto do app

Você pode evitar declarar o elemento screenOrientation do manifesto do app, o que define a orientação padrão como unspecified, ou pode definir a orientação da tela como fullUser. Se o usuário não tiver bloqueado a rotação com base no sensor, o app vai oferecer suporte a todas as orientações do dispositivo.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

A diferença entre usar unspecified e fullUser é sutil, mas importante. Se você não declarar um valor screenOrientation, o sistema vai escolher a orientação, e a política usada para defini-la poderá variar de acordo com o dispositivo. Por outro lado, especificar fullUser corresponde mais de perto ao comportamento que o usuário definiu para o dispositivo: se o usuário tiver bloqueado a rotação com base em sensor, o app vai seguir a preferência do usuário. Caso contrário, o sistema vai permitir qualquer uma das quatro orientações de tela possíveis (retrato, paisagem, retrato invertido ou paisagem invertida). Consulte android:screenOrientation.

2. Restringir dinamicamente a orientação no Compose

No Jetpack Compose, é possível ler as dimensões atuais da tela em DPs de forma reativa em LocalConfiguration.current e usar um LaunchedEffect para atualizar a orientação da atividade sempre que a configuração mudar.

Se a largura ou a altura da tela for menor que 600dp (correspondente ao ponto de interrupção compacto para smartphones), restrinja a orientação ao modo retrato. Caso contrário, permita que o sistema gire o app com base na preferência do usuário (unspecified ou fullUser).

Confira a implementação completa e compilável:

val configuration = LocalConfiguration.current
val context = LocalActivity.current

LaunchedEffect(configuration) {
    val activity = context ?: return@LaunchedEffect
    // Determine if screen is compact (phone-sized) in either width or height
    val isCompact = configuration.screenWidthDp < 600 || configuration.screenHeightDp < 600
    activity.requestedOrientation = if (isCompact) {
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    } else {
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    }
}

Ao adicionar a lógica dentro de um bloco LaunchedEffect(configuration), você pode substituir de forma reativa a configuração de orientação sempre que a configuração do app mudar, por exemplo, quando a atividade for redimensionada, movida entre telas ou quando um dispositivo dobrável for dobrado ou desdobrado.

Para mais informações sobre quando as mudanças de configuração ocorrem e quando elas causam a recriação de atividades, consulte Gerenciar mudanças de configuração.

Resultados

Agora, o app vai permanecer na orientação retrato em telas pequenas, independente da rotação do dispositivo. Em telas grandes, o app precisa oferecer suporte às orientações de paisagem e retrato.

Outros recursos

Para receber ajuda com o upgrade do app para que ele ofereça suporte a todas as configurações de dispositivos o tempo todo, consulte: