Gerenciador de Janelas do Jetpack para dispositivos dobráveis

O Gerenciador de Janelas do Jetpack fornece uma API padrão para trabalhar com todos os dispositivos dobráveis. Ele contém duas classes importantes:

  • DisplayFeature – identifica as interrupções na superfície de tela plana contínua, como dobradiças ou dobras. O Gerenciador de Janelas retornará uma coleção de recursos de exibição de um retorno de chamada de alteração de layout.
  • FoldingFeature – fornece informações sobre um recurso específico do dispositivo. Embora o Surface Duo tenha apenas um recurso de dobragem, é possível que outros dispositivos tenham mais.

Um guia semelhante está no Codelab Dobrável para Android. Leia mais sobre como desenvolver para dobráveis nos documentos do Android. Exemplos da equipe do Android também estão disponíveis no GitHub. As notas sobre a versão do Jetpack registram alterações no Gerenciador de Janelas conforme ele é atualizado.

Dica

Os controles e as classes auxiliares na biblioteca de tela dupla do Surface Duo funcionam com o Gerenciador de Janelas. Siga as instruções para adicionar os pacotes corretos ao seu projeto de aplicativo.

Para usar o Gerenciador de Janelas diretamente no seu código, siga as instruções abaixo:

Adicionar dependências

  1. Verifique se você tem o repositório mavenCentral() no arquivo build.gradle de nível superior:

    allprojects {
        repositories {
            google()
            mavenCentral()
         }
    }
    
  2. Verifique se compileSdkVersion e targetSdkVersion estão configurados para a API 31 ou mais recente no seu arquivo build.gradle de nível de módulo:

    android { 
        compileSdkVersion 31
    
        defaultConfig { 
            targetSdkVersion 31
        } 
        ... 
    }
    
    
  3. Adicione as seguintes dependências ao arquivo build.gradle de nível de módulo:

    dependencies {
        implementation "androidx.window:window:1.0.0"
        implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
    }
    

Usar o Gerenciador de Janelas em seu código Kotlin

Ao acessar as propriedades do Gerenciador de Janelas nos seus projetos Kotlin, é importante configurar o fluxo correto de informações. Caso contrário, você poderá receber poucas atualizações de eventos ou atualizações demais, e o desempenho do aplicativo poderá ser afetado.

Para inicializar e usar um objeto WindowInfoTracker, siga as etapas abaixo:

  1. Na classe MainActivity, crie uma variável para o WindowInfoTracker. Verifique se o import androidx.window.layout.WindowInfoTracker foi adicionado à parte superior do arquivo.

    class MainActivity : AppCompatActivity() {
        private lateinit var windowInfoTracker: WindowInfoTracker
    
  2. Inicialize o WindowInfoTracker no método onCreate da sua atividade e configure um fluxo para coletar informações da propriedade windowLayoutInfo.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        // Initialize the window manager
        windowInfoTracker = WindowInfoTracker.getOrCreate(this@MainActivity)
    
        // Set up a flow
        lifecycleScope.launch(Dispatchers.Main) {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                windowInfoTracker.windowLayoutInfo(this@MainActivity)
                    .collect { 
                        // Check FoldingFeature properties here
                    }
            }
        }
    }
    

    Verifique se estas importações também estão adicionadas à parte superior do arquivo:

    import androidx.lifecycle.Lifecycle
    import androidx.lifecycle.lifecycleScope
    import androidx.lifecycle.repeatOnLifecycle
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.flow.collect
    import kotlinx.coroutines.launch
    
  3. Adicione o código para verificar se o fluxo WindowLayoutInfo tem as propriedades de recurso de dobragem. Quando esse código for executado, a atividade será atualizada com a postura atual do dispositivo e os recursos de exibição (se distribuídos na dobra ou dobradiça).

    No snippet de código abaixo, a atividade exibe um texto diferente com base nas propriedades de um FoldingFeature.

    Este exemplo tem um TextView chamado layout_change_text que mostra o tipo de oclusão e o valor isSeparating de todos os recursos de dobragem detectados.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        windowInfoTracker = WindowInfoTracker.getOrCreate(this@MainActivity)
    
        lifecycleScope.launch(Dispatchers.Main) {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                windowInfoTracker.windowLayoutInfo(this@MainActivity)
                    .collect { newLayoutInfo ->
                        layout_change_text.text = "No display features detected"
                        for (displayFeature : DisplayFeature in newLayoutInfo.displayFeatures) {
                            if (displayFeature is FoldingFeature && displayFeature.occlusionType == FoldingFeature.OcclusionType.NONE) {
                                layout_change_text.text = "App is spanned across a fold, " +
                                    "isSeparating = ${displayFeature.isSeparating}"
                            }
                            if (displayFeature is FoldingFeature && displayFeature.occlusionType == FoldingFeature.OcclusionType.FULL) {
                                layout_change_text.text = "App is spanned across a hinge, " +
                                    "isSeparating = ${displayFeature.isSeparating}"
                            }
                        }
                    }
            }
        }
    }
    

Propriedades do recurso de dobragem

A classe WindowLayoutInfo tem uma coleção de itens DisplayFeature, um ou mais dos quais podem ser instâncias da classe FoldingFeature.

Os recursos de dobragem têm as seguintes propriedades:

  • bounds – coordenadas do retângulo delimitador de um recurso de dobragem
  • occlusionType – informa se um recurso de dobragem oculta o conteúdo (FULL ou NONE)
  • orientation – orientação de um recurso de dobragem (HORIZONTAL ou VERTICAL)
  • state – ângulo de um recurso de dobragem (HALF_OPENED ou FLAT)
  • isSeparating – informa se um recurso de dobragem separa a área de exibição em duas seções distintas

Você pode consultar essas propriedades para tomar decisões sobre como ajustar seu layout após as alterações de configuração.

isSeparating

Ao decidir onde colocar os controles ou quantos painéis de conteúdo mostrar, use a propriedade isSeparating. Esse campo garante que o seu aplicativo forneça a melhor experiência do usuário em todos os dispositivos dobráveis:

  • Para dispositivos de tela dupla, isso sempre será verdadeiro quando um aplicativo for distribuído pela dobradiça
  • Para outros dispositivos dobráveis, isso só será verdadeiro quando o estado for HALF_OPENED, como quando um dispositivo estiver na horizontal

Use a propriedade isSeparating para decidir se deseja adaptar o layout da interface do usuário do aplicativo para um dispositivo dobrável ou usar a interface do usuário padrão quando não houver separação:

private fun updateCurrentLayout(newLayoutInfo: WindowLayoutInfo) {
   for (displayFeature in newLayoutInfo.displayFeatures) {
       val foldFeature = displayFeature as? FoldingFeature
       foldFeature?.let {
           if (it.isSeparating) {
               // The content is separated by the FoldingFeature.
               // Here is where you should adapt your UI.
           } else {
               // The content is not separated.
               // Users can see and interact with your UI properly.
           }
       }
   }
}

Para ver um exemplo mais elaborado de como usar esse campo, confira este exemplo de isSeparating.

O Google também fornece documentação e exemplos relacionados a essa propriedade como parte das diretrizes dele sobre dispositivos dobráveis e de tela grande.

Exemplos

O repositório do GitHub surface-duo-jetpack-window-manager-samples contém vários exemplos de Kotlin que demonstram diferentes padrões de experiência do usuário de tela dupla criados usando o Gerenciador de Janelas do Jetpack e o sistema de exibição tradicional.

O repositório GitHub surface-duo-compose-samples também tem exemplos de Kotlin de tela dupla que usam o Gerenciador de Janelas do Jetpack, mas nestes exemplos a interface do usuário é criada com o Jetpack Compose.

API Java

Veja a postagem no blog sobre Gerenciador de Janelas do Jetpack com Java e esse exemplo do Java para ver como acessar a classe WindowInfoTracker por meio do WindowInfoTrackerCallbackAdapter.

Recursos