Como gerenciar janelas

O ChromeOS é compatível com apps Android em várias janelas. O sistema renderiza apps em contêineres de janela cujo tamanho é determinado pelo formato do dispositivo, conforme mostrado na figura 1.

Uma janela de app em dispositivos diferentes.
Figura 1: A legenda aparece aqui.

Figura 1. Uma janela de app em dispositivos diferentes.

É importante projetar layouts que funcionem com diferentes tamanhos de tela. Se você seguir as diretrizes do Android para compatibilidade com diferentes tamanhos de tela, seu app também vai funcionar bem no ChromeOS.

Esta página mostra como ajudar a janela do seu app a ser iniciada corretamente, ser redimensionada com facilidade e exibir todo o conteúdo quando o tamanho mudar.

Tamanho inicial de inicialização

Os apps podem solicitar o tamanho inicial de inicialização das seguintes maneiras:

  • Use um tamanho de inicialização somente em ambientes de área de trabalho. Isso ajuda o gerenciador de janelas a informar os limites e a orientação corretos. Para indicar uma preferência usada no modo de área de trabalho, adicione as seguintes metatags na <activity>:

    &lt;meta-data android:name=&#34;WindowManagerPreference:FreeformWindowSize&#34;
               android:value=&#34;[phone|tablet|maximize]&#34; /&gt;
    &lt;meta-data android:name=&#34;WindowManagerPreference:FreeformWindowOrientation&#34;
               android:value=&#34;[portrait|landscape]&#34; /&gt;
    
  • Use limites de inicialização estáticos. Use <layout> na entrada do manifesto da sua atividade para especificar um tamanho inicial "fixo", como no exemplo a seguir:

    &lt;layout android:defaultHeight=&#34;500dp&#34;
                android:defaultWidth=&#34;600dp&#34;
                android:gravity=&#34;top|end&#34;
                android:minHeight=&#34;450dp&#34;
                android:minWidth=&#34;300dp&#34; /&gt;
    
  • Use limites de inicialização dinâmicos. Uma atividade pode criar e usar ActivityOptions.setLaunchBounds(Rect) ao criar uma nova atividade. Ao especificar um retângulo vazio, seu app pode ser maximizado.

Redimensionar janelas

No ChromeOS, os usuários podem redimensionar a janela de um app normalmente: arrastando o canto inferior direito, conforme mostrado na figura 2.

Figura 2: A legenda aparece aqui.

Figura 2. Uma janela redimensionável do app.

Há duas opções para gerenciar o redimensionamento de janelas ao usar a classe View:

  • Responder dinamicamente às mudanças de configuração chamando onConfigurationChanged(..). Por exemplo, você pode adicionar android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" ao manifesto da atividade. Para mais informações sobre como gerenciar mudanças de configuração, leia Gerenciar mudanças de configuração.
  • Deixar o sistema reiniciar a atividade. Nesse caso, implemente onSaveInstanceState e use o componente de arquitetura ViewModel para restaurar o estado salvo anteriormente.

Ao usar o Jetpack Compose, o comportamento de redimensionamento depende de como sua atividade está configurada. Se ele processar as mudanças de forma dinâmica, uma recomposição será acionada quando o tamanho da janela mudar. Se a atividade for reiniciada pelo sistema, uma composição inicial vai ocorrer após a reinicialização. De qualquer forma, é importante criar layouts do Compose que se adaptem às mudanças nos tamanhos das janelas. Não presuma tamanhos fixos.

Dimensões da janela

Faça com que suas atividades leiam as dimensões da janela sempre que forem iniciadas e organize o conteúdo de acordo com a configuração atual.

Para determinar a configuração atual, chame getResources().getConfiguration() na atividade atual. Não use a configuração da atividade em segundo plano ou do recurso do sistema. A atividade em segundo plano não tem um tamanho, e a configuração do sistema pode conter várias janelas com tamanhos e orientações conflitantes. Portanto, nenhum dado utilizável pode ser extraído.

Os tamanhos da janela e da tela não são iguais. Para ver o tamanho da janela no DP, use Activity.getResources().getConfiguration().screenWidth e Activity.getResources().getConfiguration().screenHeight. Você provavelmente nunca precisará usar o tamanho da tela.

Limites de conteúdo

Os limites de conteúdo de uma janela podem ser mudados após o redimensionamento. Por exemplo, a área dentro da janela usada pelo app pode mudar se a janela ficar grande demais para caber na tela. Siga as seguintes diretrizes:

  • Os apps que usam o processo de layout do Android são automaticamente dispostos no espaço disponível.
  • Os apps nativos precisam ler a área disponível e monitorar as mudanças de tamanho para evitar a existência de elementos de IU inacessíveis. Chame os métodos a seguir para determinar o tamanho inicial disponível para essa superfície:

    • NativeActivity.mLastContent[X/Y/Width/Height]()
    • findViewById(android.R.id.content).get[Width/Height]()

    O monitoramento contínuo pode ser feito usando um observador:

    • NativeActivity.onContentRectChangedNative()
    • NativeActivity.onGlobalLayout()
    • Adicionar um listener a view.addOnLayoutChangeListener(findViewById(android.R.id.content))

    Se o app pré-dimensionar a arte, faça isso sempre que a resolução mudar.

Redimensionamento em formato livre

O ChromeOS permite que qualquer janela seja redimensionada livremente: o usuário pode mudar a largura, a altura e a posição de uma janela na tela. Muitos apps para Android são criados sem o redimensionamento livre. Considere estes problemas:

  • A posição da tela pode mudar. Sempre use o sistema para realizar transformações de coordenadas de janela para tela e de tela para janela.
  • Se você estiver usando o sistema de visualização do Android, o layout da janela mudará automaticamente com uma mudança de tamanho.
  • Se você não usa o sistema de visualização e controla a superfície, o app precisará processar as mudanças de tamanho por conta própria.
  • Para apps nativos, use os membros mLastContent ou a visualização de conteúdo para determinar o tamanho inicial.
  • Quando o app estiver em execução, detecte eventos onContentRectChangedNative ou onGlobalLayout para reagir a mudanças de tamanho.
  • Com uma mudança de tamanho, o app precisará redimensionar ou recarregar layouts e elementos de arte e atualizar áreas de entrada.

Modo de tela cheia

O modo de tela cheia funciona da mesma forma que no Android. Se a janela não estiver cobrindo a tela inteira, solicitações de tela cheia (ocultando todos os elementos da interface do sistema) serão ignoradas. Quando o app for maximizado os métodos normais de tela cheia, layouts e funções serão executados. Isso ocultará os elementos da IU do sistema (barra de controle da janela e a estante).

Orientação da tela

A orientação mais comum de um app para Android é retrato, porque é assim que a maioria dos smartphones é usada. Embora a orientação retrato seja indicada para smartphones, não é adequada para laptops e tablets, em que é preferível a orientação paisagem. Para conseguir os melhores resultados para seu app, ofereça compatibilidade para as duas orientações.

Alguns apps para Android presumem que quando um dispositivo é colocado no modo retrato, o valor de rotação é Surface.ROTATION_0. Isso é válido para a maioria dos dispositivos Android. No entanto, quando o app está em um determinado modo ARC, o valor de rotação para a orientação retrato pode não ser Surface.ROTATION_0.

Para ter um valor de rotação preciso ao ler o acelerômetro ou sensores semelhantes, use o método Display.getRotation() e troque o eixo corretamente.

A atividade raiz e a orientação

Uma janela do Chromebook consiste em uma pilha de janelas de atividade. Todas as janelas da pilha têm o mesmo tamanho e orientação.

Mudanças repentinas de orientação e tamanho são confusas em um ambiente de área de trabalho. O gerenciador de janelas do Chromebook evita isso de maneira semelhante ao modo lado a lado do Android: a atividade na parte de baixo da pilha controla os atributos de todas as atividades acima dela. Isso pode causar situações inesperadas em que uma atividade recém-iniciada, não redimensionável no modo retrato, se torna redimensionável no modo paisagem.

Nesse caso, o modo dispositivo faz diferença: no modo tablet, a orientação não é bloqueada, e cada janela preserva a própria orientação, como é normal no Android.

Diretrizes de orientação

Siga estas diretrizes para gerenciar a orientação:

  • Se você oferecer compatibilidade a apenas um modo, adicione as informações ao manifesto para que o gerenciador de janelas saiba disso antes de iniciar o aplicativo. Ao especificar a orientação, especifique também as orientações do sensor, quando possível. Os Chromebooks costumam ser conversíveis, e um app de cabeça para baixo é uma experiência ruim para o usuário.
  • Tente manter uma única orientação selecionada. Evite solicitar uma orientação no manifesto e definir outra programaticamente mais tarde.
  • Tenha cuidado ao mudar a orientação com base no tamanho da janela. O usuário pode ficar preso em uma pequena janela de retrato e não conseguir retornar a uma janela maior de paisagem.
  • Há controles de janela no Chrome para alternar entre todos os layouts disponíveis. Ao escolher a opção de orientação correta, você garante que o usuário terá o layout certo ao iniciar o app. Se um app estiver disponível nos modos retrato e paisagem, sempre que possível, o modo paisagem será o padrão. Depois de definida, essa opção é memorizada em cada app.
  • Evite mudanças de orientação desnecessárias. Por exemplo, se a orientação da atividade for retrato, mas o app chamar setRequestedOrientation(LANDSCAPE) no momento da execução, isso causará redimensionamento desnecessário da janela, o que é irritante para o usuário e pode reiniciar o app se ele não conseguir processar. É melhor definir a orientação uma vez, por exemplo, no manifesto e mudá-la se necessário.

Outras considerações

Veja algumas outras coisas a serem consideradas ao trabalhar com apps Android no ChromeOS:

  • Não chame finish() no método onDestroy da sua atividade. Com isso, o app fecha depois do redimensionamento e não é reiniciado.
  • Não use tipos de janela incompatíveis, como TYPE_KEYGUARD e TYPE_APPLICATION_MEDIA.
  • Faça reinicializações rápidas de atividades armazenando em cache objetos que foram alocados anteriormente.
  • Se você não quiser que o usuário redimensione o app, especifique android:resizeableActivity=false no arquivo de manifesto.
  • Teste o app para garantir que ele processe corretamente as mudanças no tamanho da janela.