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 ou em dispositivos dobráveis abertos.
Como você pode aproveitar o melhor de dois mundos, restringindo o app à orientação retrato na tela externa de um dispositivo dobrável, mas ativando o modo paisagem na tela interna?
Este guia é uma medida temporária até que você possa melhorar o app para oferecer suporte total a todas as configurações de dispositivos.
Resultados
O app vai permanecer na orientação retrato em telas pequenas, independente da rotação do dispositivo. Em telas grandes, o app oferece suporte às orientações paisagem e retrato.
Compatibilidade de versões
Essa implementação é compatível com todos os níveis de API.
Dependências
Kotlin
implementation("androidx.window:window:1.5.1")
implementation("androidx.window:window-core:1.5.1")
Groovy
implementation "androidx.window:window:1.5.1"
implementation "androidx.window:window-core:1.5.1"
Gerenciar a orientação do app
Para ativar a orientação paisagem em telas grandes, defina o manifesto do app para processar mudanças de orientação por padrão. Durante a execução, determine o tamanho da janela do app. Se a janela do app for pequena, restrinja a orientação do app substituindo a configuração de orientação no manifesto.
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 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 definido pelo usuário para o dispositivo: se o usuário tiver bloqueado a rotação com base em sensor, o app vai seguir a preferência dele. Caso contrário, o sistema vai permitir qualquer uma das quatro orientações de tela possíveis (retrato, paisagem, retrato invertido ou paisagem invertida).
Além disso, você pode usar nosensor para determinar a orientação sem considerar os dados do sensor, mas o código a seguir vai funcionar da mesma forma.
Consulte screenOrientation.
2. Determinar o tamanho da tela
Com o manifesto definido para oferecer suporte a todas as orientações permitidas pelo usuário, você pode especificar a orientação do app de forma programática com base no tamanho da tela.
Adicione as bibliotecas do Jetpack WindowManager ao arquivo build.gradle ou
build.gradle.kts do módulo:
Kotlin
implementation("androidx.window:window:version") implementation("androidx.window:window-core:version")
Groovy
implementation 'androidx.window:window:version' implementation 'androidx.window:window-core:version'
Use o método WindowMetricsCalculator#computeMaximumWindowMetrics() do Jetpack WindowManager para obter o tamanho da tela do dispositivo como um objeto WindowMetrics. As métricas da janela podem ser comparadas a classes de tamanho de janela para decidir quando restringir a orientação.
As classes de tamanho de janelas oferecem os pontos de interrupção entre telas pequenas e grandes.
Use os pontos de interrupção WindowSizeClass#minWidthDp e WindowSizeClass#minHeightDp para determinar o tamanho da tela:
/** Determines whether the device has a compact screen. **/
fun compactScreen() : Boolean {
val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
val width = metrics.bounds.width()
val height = metrics.bounds.height()
val density = resources.displayMetrics.density
val windowSizeClass =
BREAKPOINTS_V1.computeWindowSizeClass(width / density, height / density)
return windowSizeClass.minWidthDp == 0
}
- Observação:
- Os exemplos são implementados como métodos de uma atividade. A atividade é desreferenciada como
thisno argumento decomputeMaximumWindowMetrics(). - O método
computeMaximumWindowMetrics()é usado em vez decomputeCurrentWindowMetrics()porque o app pode ser iniciado no modo de várias janelas, o que ignora a configuração de orientação da tela. Não há sentido em determinar o tamanho da janela do app e substituir a configuração de orientação, a menos que a janela do app seja a tela inteira do dispositivo.
Consulte WindowManager para instruções sobre como declarar dependências e disponibilizar o
método computeMaximumWindowMetrics() no app.
3. Substituir a configuração do manifesto do app
Se você determinar que o dispositivo tem um tamanho de tela compacto, chame
Activity#setRequestedOrientation() para substituir a configuração
screenOrientation do manifesto:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestedOrientation = if (compactScreen())
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
ActivityInfo.SCREEN_ORIENTATION_FULL_USER
...
// Replace with a known container that you can safely add a
// view to where the view won't affect the layout and the view
// won't be replaced.
val container: ViewGroup = binding.container
// Add a utility view to the container to hook into
// View.onConfigurationChanged. This is required for all
// activities, even those that don't handle configuration
// changes. You can't use Activity.onConfigurationChanged,
// since there are situations where that won't be called when
// the configuration changes. View.onConfigurationChanged is
// called in those scenarios.
container.addView(object : View(this) {
override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
requestedOrientation = if (compactScreen())
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
ActivityInfo.SCREEN_ORIENTATION_FULL_USER
}
})
}
Ao adicionar a lógica aos métodos onCreate() e View.onConfigurationChanged(), você poderá acessar as métricas máximas da janela e substituir a configuração de orientação sempre que a atividade for redimensionada ou movida entre as telas, por exemplo, após uma rotação do dispositivo 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.
Se você estiver usando o Jetpack Compose, poderá usar a mesma função compactScreen()
no elemento combinável raiz do app para ter o mesmo resultado.
Pontos principais
screenOrientation: configuração do manifesto do app que permite especificar como o aplicativo responde às mudanças de orientação do dispositivo.- Jetpack WindowManager: conjunto de bibliotecas que permite determinar o tamanho e a proporção da janela do app. Ele é compatível com versões anteriores até o nível 14 da API.
Activity#setRequestedOrientation(): método com que é possível mudar a orientação do app no momento da execução.
Coleções que contêm este guia
Este guia faz parte das coleções de guias rápidos selecionados que abordam metas mais amplas de desenvolvimento para Android: