O modo de múltiplas janelas de formato livre é um recurso subutilizado e subestimado no Android Nougat. Explicamos o que é e como os desenvolvedores podem incorporá-lo.
Quando o Android 7.0 Nougat foi anunciado pela primeira vez no início de 2016, ele trouxe consigo um recurso muito solicitado para a plataforma Android: suporte para múltiplas janelas. A maioria das pessoas está ciente do suporte para múltiplas janelas de tela dividida habilitado por padrão em todos os telefones e tablets Android Nougat. Dispositivos Android TV com Android Nougat vêm com suporte para múltiplas janelas picture-in-picture.
No entanto, há um terceiro modo de múltiplas janelas presente no Android Nougat que poucas pessoas conhecem: modo de janela de forma livre. Este modo permite que o Android apresente aplicativos como janelas flutuantes que podem ser movidas e redimensionadas à vontade do usuário. É essencialmente a implementação do Android de um gerenciador de janelas de empilhamento.
No Documentação do Android SDK, Afirma que:
Os fabricantes de dispositivos maiores podem optar por ativar o modo de forma livre, no qual o usuário pode redimensionar livremente cada atividade. Se o fabricante ativar esse recurso, o dispositivo oferecerá o modo de forma livre, além do modo de tela dividida.
E também, no Android 7.0 CDD:
Implementações de dispositivos com tamanho de tela xlarge DEVEM suportar o modo de forma livre.
Isso indica que qualquer novo dispositivo Android de tela grande fornecido com Android 7.0 pode ter o modo de janela de formato livre habilitado pelo fabricante.
No entanto, este não é um requisito difícil. É possível forçar qualquer Dispositivo Android Nougat (com opções de desenvolvedor ativadas) para oferecer suporte ao modo de janela de formato livre usando um dos dois métodos diferentes:
Ativando o modo de janela de formato livre em qualquer dispositivo Android Nougat
Método 1 (é necessário um computador com adb)
Certifique-se de que a depuração USB esteja habilitada nas opções do desenvolvedor. Em seguida, conecte seu dispositivo a um computador com o adb instalado e execute o seguinte comando:
adb shell settings put global enable_freeform_support 1
Método 2 (sem requisitos adicionais)
Ative a opção “Forçar atividades redimensionáveis” na parte inferior das Opções do desenvolvedor.
Ambos os métodos exigem que a IU do sistema seja reiniciada antes de entrarem em vigor. A maneira mais fácil de fazer isso é reinicializar o seu dispositivo (ou, se o seu dispositivo estiver enraizado, você pode simplesmente matar o com.android.systemui
processo)
OK, então o modo de forma livre está ativado… e agora?
Se você ativou o modo de forma livre usando o Método 1, haverá um novo botão nas entradas do aplicativo no menu Visão geral para iniciar um aplicativo no modo de janela de forma livre.
Com o Método 2, entretanto, não é possível iniciar um aplicativo no modo de forma livre através do próprio Android. Felizmente, é possível para qualquer iniciador de terceiros iniciar um aplicativo no modo de janela de formato livre usando APIs padrão do Android que foram finalizadas como parte da API de nível 24.
A chave para iniciar um aplicativo no modo de forma livre é chamar o ActivityOptions.setLaunchBounds()
método. Este método leva um Rect
como argumento, contendo os limites da janela com a qual o aplicativo será iniciado.
Você pode então iniciar o aplicativo com startActivity(Intent, Bundle)
. Se você ainda não tem um ActivityOptions
pacote, você pode criar um com ActivityOptions.makeBasic()
e depois ligando setLaunchBounds()
no pacote recém-criado.
Observe que, por padrão, se já houver uma tarefa para o aplicativo presente na tela Visão geral, então O Android irá simplesmente redirecioná-lo para a tarefa existente (tela cheia) que foi iniciada anteriormente pelo do utilizador. Você precisará limpar todas as tarefas do aplicativo em Visão geral antes de tentar iniciar o aplicativo em uma janela de formato livre. (Para aplicativos com atividades iniciadas em standard
ou singleTop
modos, você pode forçar a abertura de uma nova janela adicionando o Intent.FLAG_ACTIVITY_MULTIPLE_TASK
sinalizar para a intenção antes de ligar startActivity()
.)
Como funciona o modo de forma livre nos bastidores?
Há um excelente artigo escrito que explica como o modo multijanela, incluindo o modo de forma livre, é implementado no Android Nougat. (NOTA: o artigo está escrito em chinês, portanto, certifique-se de executá-lo no Google Translate)
Resumindo, os aplicativos no modo de forma livre são executados em uma pilha separada do resto do sistema (pense: área de trabalho virtual). Portanto, não é possível que aplicativos de formato livre sejam executados no iniciador ou em outro aplicativo de tela inteira.
Aplicativos executados no modo de formato livre (que não possuem android: windowIsFloating
definido como verdadeiro) tem um DecorCaptionView
adicionado como filho do nível superior DecorView
. Esta visão contém um LinearLayout
definindo a barra de legenda da janela para mover, maximizar e fechar a janela. Embora eu não recomende isso pessoalmente, é possível acessar e personalizar essa visualização obtendo o DecorView
usando Window.getDecorView()
, lançando-o para um ViewGroup
e então acessando suas visualizações filhas.
Qualquer aplicativo projetado para se comportar bem no modo de tela dividida multijanela padrão do Android funcionará no modo de forma livre. isInMultiWindowMode()
retornará verdadeiro para aplicativos executados no modo de forma livre. Existem algumas outras classes e métodos disponíveis publicamente que um aplicativo pode usar e que se relacionam especificamente ao modo de forma livre:
-
Window.setDecorCaptionShade()
: este método pode ser usado para substituir a sombra dos controles de legenda (o botão maximizar e fechar) para aplicativos no modo de forma livre. -
Window.setRestrictedCaptionAreaListener()
: pode ser usado para detectar quando uma janela é movida no modo de forma livre. OWindow.OnRectrictedCaptionAreaChangedListener
é chamado sempre que a posição dos controles de legenda muda (quando um usuário move a janela) e fornece umRect
com os novos limites dos controles de legenda. -
ActivityInfo.WindowLayout
: esta classe contém informações declaradas no manifesto do aplicativo quanto ao posicionamento inicial de uma janela de formato livre que um aplicativo pode solicitar na inicialização. Por exemplo, você pode listar o seguinte no tag do seu manifesto:
Então, quando o dispositivo já estiver no modo de forma livre e o aplicativo for iniciado, ele será iniciado com esses limites especificados.android: defaultHeight="640dp"
android: defaultWidth="360dp"
android: gravity="center" />
Exemplos de modo de janela de formato livre em ação
No verão de 2016, enquanto o Android Nougat ainda era uma prévia do desenvolvedor, lancei um aplicativo chamado Barra de tarefas que fornece um menu iniciar semelhante ao do Windows e uma lista de aplicativos recentes em uma sobreposição do sistema. Ele permite que os usuários do Nougat iniciem aplicativos no modo de janela de formato livre – e, como a barra de tarefas usa uma sobreposição, ela pode permanecer na tela no ambiente de janela de formato livre. A combinação da barra de tarefas e do modo de forma livre dá a qualquer dispositivo Android, especialmente tablets, uma sensação de PC.
Você pode baixar barra de tarefas no Google Play ou veja o código fonte você mesmo no GitHub. Além dos conceitos mencionados neste artigo, também utilizo alguns truques para manter o ambiente do modo de forma livre ativo mesmo quando nenhuma janela de forma livre é exibida na tela. Os usuários também podem definir opcionalmente a Barra de Tarefas como seu inicializador padrão para permitir que seu dispositivo inicialize automaticamente no ambiente de modo de forma livre.
Como não há dispositivos fornecidos oficialmente com suporte a janelas de formato livre habilitado pelo OEM (no momento em que este livro foi escrito), recomendo usando a barra de tarefas como uma ferramenta para os desenvolvedores testarem seus aplicativos no ambiente de janela de formato livre em dispositivos que de outra forma não suportam isto.
Além da barra de tarefas, também modifiquei o código-fonte do Launcher3 do AOSP para permitir o lançamento de aplicativos no modo de forma livre. Este é um clone direto do inicializador padrão do Android 7.1.1, com as modificações mínimas necessárias para permitir o lançamento de aplicativos de formato livre. Forneci este inicializador modificado na esperança de que outros desenvolvedores implementem suporte para iniciar janelas de formato livre em seus inicializadores personalizados. Você pode veja o código fonte no GitHub ou baixe um exemplo de APK.
Minha esperança é que os desenvolvedores de lançadores personalizados possam utilizar este código e habilitar suporte para lançamento de forma livre aplicativos de janela para aqueles usuários que desejam maior flexibilidade para gerenciamento de janelas em suas telas grandes dispositivos.