Compatibilidade com Várias janelas

O Android 7.0 adiciona suporte à exibição de mais de um aplicativo ao mesmo tempo. Em dispositivos portáteis, dois aplicativos podem ser executados lado a lado ou um acima do outro no modo de tela dividida. Em dispositivos de TV, os aplicativos podem usar o modo picture-in-picture para continuar a reprodução do vídeo enquanto os usuários interagem com outro aplicativo.

Caso seu aplicativo seja direcionado ao Android 7.0 (API de nível 24) ou superior, é possível configurar como o aplicativo lidará com a exibição em várias telas. Por exemplo, você pode especificar as dimensões mínimas permitidas para a atividade. Você também pode desativar a exibição em várias janelas para o aplicativo, garantindo que o sistema mostre o aplicativo somente em modo de tela cheia.

Visão geral

O Android permite que diversos aplicativos compartilhem a tela ao mesmo tempo. Por exemplo, um usuário pode dividir a tela para visualizar uma página da Web no lado esquerdo e compor um e-mail no lado direito. A experiência do usuário depende da versão do SO do Android e do tipo de dispositivo:

  • Os dispositivos portáteis que executam o Android 7.0 oferecem o modo de tela dividida. Nesse modo, o sistema preenche a tela com dois aplicativos, exibindo-os lado a lado ou um acima do outro. O usuário pode arrastar a linha divisória que separa os dois para que um aplicativo fique maior e o outro menor.
  • A partir do Android 8.0, os aplicativos podem se apresentar no modo picture-in-picture, o que permite que continuem a exibir conteúdo enquanto o usuário procura ou interage com outros aplicativos.
  • Fabricantes de dispositivos maiores podem optar pelo modo de forma livre, em que o usuário pode redimensionar livremente cada atividade. Se o fabricante ativar esse recurso, o dispositivo oferecerá o modo de forma livre e o modo de tela dividida.

Figura 1. Dois aplicativos executando lado a lado em modo de tela dividida.

O usuário pode mudar para o modo de várias janelas das seguintes maneiras:

  • Se o usuário abrir a tela “Overview” e tocar e manter pressionado um título de atividade, poderá arrastá-la para uma parte destacada da tela para colocá-la no modo Várias janelas.
  • Se o usuário tocar e manter pressionado o botão “Overview”, o dispositivo colocará a atividade atual no modo de várias janelas e abrirá a tela “Overview” para permitir que o usuário escolha outra atividade para compartilhar a tela.

Os usuários podem arrastar e soltar dados de uma atividade para outra enquanto as atividades compartilham a tela.

Ciclo de vida do modo Várias janelas

O modo Várias janelas não altera o ciclo de vida da atividade.

No modo de várias janelas, somente a atividade com que o usuário interagiu mais recentemente fica ativa em um determinado momento. Essa atividade é considerada a atividade superior e é a única no estado RESUMED. Todas as outras atividades visíveis ficam no estado STARTED, mas não em RESUMED. No entanto, o sistema atribui a essas atividades pausadas, mas visíveis, uma prioridade maior que a das atividades não visíveis. Se o usuário interagir com uma das atividades visíveis, ela será retomada e a atividade previamente superior entrará no estado STARTED.

Observação: no modo de várias janelas, um aplicativo pode não estar no estado RESUMED, mesmo que esteja visível ao usuário. Pode ser que um aplicativo precise continuar a operação, mesmo que não seja considerado como uma atividade superior. Por exemplo, um aplicativo que reproduz vídeo e que está nesse estado continuará a exibir o vídeo. Por esse motivo, recomendamos que atividades que reproduzem vídeo não pausem a reprodução em resposta ao evento de ciclo de vida ON_PAUSE. Em vez disso, a atividade precisa começar a reprodução em resposta a ON_START e pausá-la em resposta a ON_STOP. Caso você lide com eventos do ciclo de vida diretamente, em vez de usar o pacote Lifecycle, pause a reprodução do vídeo no seu gerenciador onStop() e retome a reprodução em onStart().

Quando o usuário coloca um aplicativo no modo de várias janelas, o sistema notifica a atividade sobre a mudança de configuração, como especificado em Processamento de alterações na configuração. Isso também acontece quando o usuário redimensiona o aplicativo ou coloca-o novamente no modo de tela cheia. Essencialmente, essa alteração afeta o ciclo de vida da atividade igual a quando o sistema notifica o aplicativo sobre o dispositivo ter mudado do modo de retrato para paisagem, exceto que as dimensões do dispositivo são alteradas, em vez de simplesmente trocadas. Como discutido em Processamento de alterações na configuração, sua atividade pode processar ela mesma a mudança de configuração ou permitir que o sistema destrua a atividade e recrie-a com as novas dimensões.

Se o usuário redimensionar uma janela e aumentar uma de suas dimensões, o sistema redimensionará a atividade para corresponder à ação do usuário e emitirá mudanças de configuração conforme necessário. Se o aplicativo demorar a desenhar nas áreas recém-expostas, o sistema preencherá temporariamente essas áreas com a cor especificada pelo atributo windowBackground ou pelo atributo de estilo windowBackgroundFallback padrão.

Configuração do aplicativo para o modo Várias janelas

Se seu aplicativo for direcionado à API de nível 24 ou superior, você poderá configurar como e se as atividades do aplicativo são compatíveis com a exibição em várias janelas. Você pode definir atributos no manifesto para controlar o tamanho e o layout. As configurações de atributos de uma atividade raiz se aplicam a todas as atividades na pilha de tarefas. Por exemplo, se a atividade raiz tiver android:resizeableActivity definido como “true”, todas as atividades na pilha de tarefas serão redimensionáveis.

Observação: se você criar um aplicativo com várias orientações direcionado à API de nível 23 ou inferior e o usuário usar o aplicativo no modo de várias janelas, o sistema redimensionará forçosamente o aplicativo. O sistema apresenta uma caixa de diálogo avisando o usuário de que o aplicativo pode se comportar de forma inesperada. O sistema não redimensiona aplicativos de orientação fixa. Se o usuário tentar abrir um aplicativo de orientação fixa no modo de várias janelas, o aplicativo ocupará toda a tela.

android:resizeableActivity

Defina esse atributo no elemento <activity> ou <application> do seu manifesto para ativar ou desativar a exibição em várias telas:

android:resizeableActivity=["true" | "false"]

Se esse atributo for definido como “true”, a atividade poderá ser inicializada nos modos de tela dividida e forma livre. Se o atributo for definido como “false”, a atividade não será compatível com o modo de várias janelas. Se esse valor for “false” e o usuário tentar iniciar a atividade no modo de várias janelas, a atividade ocupará a tela inteira.

Se o aplicativo for direcionado à API de nível 24, mas o valor desse atributo não for especificado, o atributo assumirá o valor padrão “true”.

android:supportsPictureInPicture

Defina esse atributo no nó <activity> do manifesto para indicar se a atividade é compatível com a exibição no modo Picture-in-Picture. Esse atributo será ignorado se android:resizeableActivity for “false”.

android:supportsPictureInPicture=["true" | "false"]

Atributos de layout

No Android 7.0, o elemento de manifesto <layout> é compatível com diversos atributos que afetam o comportamento da atividade no modo de várias janelas:

android:defaultWidth
Largura padrão da atividade quando iniciada no modo de forma livre.
android:defaultHeight
Altura padrão da atividade quando iniciada no modo de forma livre.
android:gravity
É o posicionamento inicial da atividade quando iniciada no modo de forma livre. Consulte a referência de Gravity para verificar os valores adequados.
android:minHeight, android:minWidth
Indicam altura mínima e largura mínima para a atividade nos modos de tela dividida e forma livre. Se o usuário mover o divisor no modo de tela dividida para tornar uma atividade menor que o mínimo especificado, o sistema recortará a atividade para o tamanho solicitado pelo usuário.

Por exemplo, o código a seguir mostra como especificar um tamanho e um local padrão para a atividade, bem como o tamanho mínimo, quando a atividade é exibida no modo de forma livre:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end"
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

Execução do aplicativo no modo Várias janelas

A partir do Android 7.0, o sistema oferece funcionalidade de suporte a aplicativos que podem ser executados no modo de várias janelas.

Recursos desativados no modo de várias janelas

Alguns recursos são desativados ou ignorados quando um dispositivo está no modo de várias janelas, pois não fazem sentido para uma atividade que pode estar compartilhando a tela do dispositivo com outras atividades ou aplicativos. Esses recursos incluem o seguinte:

  • Algumas opções de personalização de IU do sistema são desativadas. Por exemplo, os aplicativos não podem ocultar a barra de status se não estiverem executando no modo de tela cheia.
  • O sistema ignora as alterações no atributo android:screenOrientation.

Notificações e consultas de mudança no modo Várias janelas

Activity oferece os métodos a seguir para suporte à exibição em várias janelas.

isInMultiWindowMode()
Chame para descobrir se a atividade está no modo de várias janelas.
isInPictureInPictureMode()
Chame para descobrir se a atividade está no modo picture-in-picture.

Observação: o modo picture-in-picture é um caso especial do modo de várias janelas. Se myActivity.isInPictureInPictureMode() retornar “true”, myActivity.isInMultiWindowMode() também retornará “true”.

onMultiWindowModeChanged()
O sistema chama esse método sempre que a atividade entra ou sai do modo de várias janelas. O sistema passará ao método o valor “true” se a atividade entrar no modo de várias janelas e “false” se a atividade sair desse modo.
onPictureInPictureModeChanged()
O sistema chama esse método sempre que a atividade entra ou sai do modo picture-in-picture. O sistema passará ao método o valor “true” se a atividade entrar no modo picture-in-picture e “false” se a atividade sair desse modo.

A classe Fragment expõe versões de muitos desses métodos. Por exemplo: Fragment.onMultiWindowModeChanged().

Entrar no modo picture-in-picture

Para colocar uma atividade no modo picture-in-picture, chame Activity.enterPictureInPictureMode(). Esse método não terá efeito se o dispositivo não oferecer suporte ao modo picture-in-picture. Para mais informações, consulte a documentação do modo picture-in-picture.

Iniciar novas atividades no modo Várias janelas

Ao iniciar uma nova atividade, você pode indicar ao sistema que ela precisará ser exibida adjacente à atual, se possível. Para fazer isso, use o sinalizador de intent FLAG_ACTIVITY_LAUNCH_ADJACENT. A passagem desse sinalizador solicita o seguinte comportamento:

  • Se o dispositivo estiver no modo de tela dividida, o sistema tentará criar a nova atividade ao lado da atividade que a iniciou para que ambas compartilhem a tela. Nem sempre o sistema conseguirá fazer isso, mas as atividades ficarão adjacentes, se possível.
  • Se o dispositivo não estiver no modo de tela dividida, esse sinalizador não terá efeito.

Se um dispositivo estiver no modo de forma livre e você iniciar uma nova atividade, poderá especificar as dimensões e o local na tela da nova atividade chamando ActivityOptions.setLaunchBounds(). Esse método não terá efeito se o dispositivo não estiver no modo de várias janelas.

Observação: se você iniciar uma atividade em uma pilha de tarefas, essa atividade substituirá a atividade na tela, herdando todas as propriedades de suporte a várias janelas. Se você quiser iniciar a nova atividade como janela separada no modo de várias janelas, inicie-a em uma nova pilha de tarefas.

Suporte a arrastar e soltar

Os usuários podem arrastar e soltar dados de uma atividade para outra enquanto as duas atividades compartilham a tela. Antes do Android 7.0, os usuários podiam somente arrastar e soltar dados em uma única atividade. Por esse motivo, se o aplicativo não tiver a funcionalidade de arrastar e soltar, poderá ser uma boa ideia adicioná-la.

DragAndDropPermissions
É o objeto token responsável por especificar as permissões concedidas ao aplicativo que recebe uma ação de soltar.
View.startDragAndDrop()
É o alias para View.startDrag(). Para ativar o recurso de arrastar e soltar entre atividades, passe o sinalizador DRAG_FLAG_GLOBAL. Se você precisar conceder permissões de URI à atividade de destino, passe os sinalizadores DRAG_FLAG_GLOBAL_URI_READ ou DRAG_FLAG_GLOBAL_URI_WRITE, conforme o caso.
View.cancelDragAndDrop()
Cancela uma operação de arrastar em andamento. Somente pode ser chamado pelo aplicativo que originou a operação de arrastar.
View.updateDragShadow()
Substitui a sombra de arrastar para uma operação de arrastar em andamento. Somente pode ser chamado pelo aplicativo que originou a operação de arrastar.
Activity.requestDragAndDropPermissions()
Solicita as permissões dos URIs de conteúdo passados com o ClipData contido em um DragEvent.

Teste do suporte a Várias janelas em seu aplicativo

Mesmo que você não direcione seu aplicativo à API de nível 24 ou superior, é importante verificar como ele se comporta no modo de várias janelas, pois um usuário pode tentar iniciá-lo nesse modo em um dispositivo executando o Android 7.0 ou superior.

Configuração de um dispositivo de teste

Se um dispositivo executar o Android 7.0 ou superior, ele será automaticamente compatível com o modo de tela dividida.

Caso seu aplicativo trabalhe com API de nível 23 ou inferior

Se seu aplicativo for direcionado à API de nível 23 ou inferior e o usuário tentar usá-lo no modo de várias janelas, o sistema o redimensionará forçosamente, a menos que seja declarada uma orientação fixa.

Se o aplicativo não declarar uma orientação fixa, inicie-o em um dispositivo executando o Android 7.0 ou superior e tente colocar o aplicativo no modo de tela dividida. Verifique se a experiência do usuário é aceitável quando o redimensionamento do aplicativo é forçado.

Se o aplicativo declarar uma orientação fixa, tente colocá-lo no modo de várias janelas. Ao fazer isso, verifique se o aplicativo continua no modo de tela cheia.

Se você oferecer suporte ao modo de várias janelas

Se seu aplicativo for direcionado à API de nível 24 ou superior e não tiver desativado o suporte a várias janelas, verifique o comportamento a seguir nos modos de tela dividida e forma livre.

  • Mantenha o botão “Overview” pressionado para iniciar o aplicativo no modo de tela cheia e mudar para o modo de várias janelas. Verifique se o aplicativo alterna corretamente.
  • Inicie o aplicativo diretamente no modo de várias janelas e verifique se a inicialização ocorre corretamente. Você pode iniciar um aplicativo no modo Várias telas pressionando o botão “Overview” e, em seguida, mantendo pressionada a barra de título do aplicativo e arrastando-o a uma das áreas destacadas na tela.
  • Redimensione o aplicativo no modo de tela dividida, arrastando a linha divisória. Verifique se o aplicativo é redimensionado sem falhar e se os elementos de IU necessários estão visíveis.
  • Se você especificou dimensões mínimas para o aplicativo, tente redimensioná-lo abaixo dessas dimensões. Verifique se não é possível redimensionar o aplicativo para um tamanho menor que o mínimo especificado.
  • Em todos os testes, verifique se o desempenho do aplicativo é aceitável. Por exemplo, verifique se há uma demora muito grande para atualizar a IU após o redimensionamento do aplicativo.

Lista de verificação de teste

Para verificar o desempenho do aplicativo no modo de várias janelas, tente as seguintes operações. Tente essas operações nos modos de tela dividida e várias telas, exceto onde houver instruções diferentes.

  • Entre e saia do modo de várias janelas.
  • Alterne do seu aplicativo para outro e verifique se seu aplicativo se comporta corretamente enquanto visível, mas não ativo. Por exemplo, se seu aplicativo estiver reproduzindo vídeo, verifique se a reprodução não é interrompida quando o usuário interage com outro aplicativo.
  • No modo de tela dividida, tente mover a barra divisória para aumentar e reduzir o tamanho do aplicativo. Tente essas operações nas configurações lado a lado e um acima do outro. Verifique se o aplicativo não falha, se a funcionalidade essencial fica visível e se a operação de redimensionamento não demora demais.
  • Execute várias operações de redimensionamento em rápida sucessão. Verifique se o aplicativo não falha nem apresenta vazamento de memória. Para informações sobre como verificar o uso de memória do aplicativo, use o Memory Profiler do Android Studio.
  • Use o aplicativo normalmente em diversas configurações diferentes de janela e verifique se ele se comporta corretamente. Verifique se o texto é legível e se os elementos de IU não ficam pequenos demais para a interação.

Se você desativou o suporte a várias janelas

Se você desativou o suporte a várias janelas definindo android:resizeableActivity="false", inicie o aplicativo em um dispositivo executando Android 7.0 ou superior e tente colocá-lo nos modos de forma livre e tela dividida. Ao fazer isso, verifique se o aplicativo continua no modo de tela cheia.

Para mais informações sobre o suporte ao modo Várias janelas no Android, consulte Cinco dicas para preparar o modo Várias janelas no Android N e o aplicativo de amostra Interface com Várias janelas.