O Android permite que vários apps compartilhem a mesma tela simultaneamente. O sistema pode exibir dois apps lado a lado (modo de tela dividida), um app em uma pequena janela sobreposto a outros apps (modo picture-in-picture) ou apps individuais em janelas móveis redimensionáveis (modo de formato livre).
Figura 1. Dois apps executados lado a lado no modo de tela dividida.
A experiência do usuário depende da versão do SO Android e do tipo de dispositivo:
-
O Android 7.0 oferece o modo de tela dividida em dispositivos portáteis e o modo picture-in-picture em TVs.
O modo de tela dividida preenche a tela com dois apps, exibindo um ao lado ou um acima do outro. Os usuários podem arrastar o divisor separando os dois apps para que um fique maior e o outro menor.
O modo picture-in-picture permite que os usuários continuem a reprodução de vídeo enquanto interagem com outro app (consulte Suporte a picture-in-picture).
Fabricantes de dispositivos maiores podem optar pelo modo de formato livre, em que os usuários podem redimensionar livremente cada atividade.
Você pode configurar como seu app processa a exibição em várias janelas especificando as dimensões mínimas permitidas para a atividade. Também pode desativar a exibição em várias janelas para o app configurando
resizeableActivity="false"
para garantir que o sistema sempre mostre o app em tela cheia. - O Android 8.0 estende o modo picture-in-picture para dispositivos portáteis.
O Android 12 torna o modo de várias janelas o comportamento padrão.
Em telas grandes (maior ou igual a 600 dp), a plataforma é compatível com todos os apps no modo de várias janelas, independentemente da configuração do app. Se
resizeableActivity="false"
, o app será colocado no modo de compatibilidade quando necessário para acomodar dimensões de exibição.Em telas pequenas (com menos de 600 dp), o sistema verifica a
minWidth
eminHeight
de uma atividade para determinar se esta pode ser executada no modo de várias janelas. SeresizeableActivity="false"
, o app não poderá ser executado no modo de várias janelas, independentemente da largura e altura mínimas.Observação: os fabricantes de dispositivos podem modificar esses comportamentos.
Ativação no modo de tela dividida
Para ativar o modo de tela dividida, os usuários podem fazer o seguinte:
- Abrir a tela Recentes
- Deslizar um app para vê-lo
- Pressionar o ícone do app na barra de título
- Selecionar a opção de menu Tela dividida
- Selecionar outro app na tela Recentes ou fechar a tela Recentes e executar outro app
Os usuários podem sair do modo de tela dividida arrastando o divisor da janela para a borda da tela em qualquer direção.
Ciclo de vida do modo de várias janelas
O modo de várias janelas não muda o ciclo de vida da atividade. No entanto, o estado retomado dos apps em várias janelas varia de acordo com as diferentes versões do Android.
Retomada múltipla
No Android 10 (API de nível 29) e versões mais recentes, todas as atividades permanecem no
estado RESUMED
quando o dispositivo está no modo de várias janelas. Esse recurso é chamado de retomada múltipla.
Uma atividade poderá ser pausada se houver uma atividade transparente sobre ela
ou se a atividade não puder ser focalizada (por exemplo,
no modo picture-in-picture). Além disso,
é possível que nenhuma atividade esteja em foco em determinado momento, por exemplo, se a
gaveta de notificações estiver aberta. O método onStop
funciona normalmente. É
chamado sempre que uma atividade é retirada da tela.
O recurso de retomada múltipla também está disponível em alguns dispositivos com Android 9. Para ativar a retomada múltipla nesses dispositivos, adicione os seguintes metadados do manifesto:
<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />
Para verificar se determinado dispositivo é compatível com esses metadados do manifesto, consulte as especificações do dispositivo.
Android 9
No modo de várias janelas no Android 9 (API de nível 28) e versões anteriores, somente a atividade
com que o usuário interagiu mais recentemente fica ativa em determinado momento. Essa
atividade é considerada a mais importante 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 que antes era a mais importante entrará no
estado
STARTED
.
Quando houver várias atividades em um único processo de app ativo, a atividade com a ordem z mais alta será retomada, e as outras serão pausadas.
Observação: no modo de várias janelas no Android 9 e versões anteriores, um app
pode não estar no estado
RESUMED
, mesmo que ela esteja visível para o usuário, mas
o app precisa continuar a operação, mesmo que não seja considerada a atividade principal. Por
exemplo, um app de vídeo nesse estado deve continuar a reprodução do 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ê processe eventos de 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()
.
Mudanças de configuração
Quando o usuário coloca um app no modo de várias janelas, o sistema notifica a atividade sobre uma mudança na configuração, como especificado em Gerenciar alterações de configuração. Isso também acontece quando o usuário redimensiona o app ou o coloca novamente no modo de tela cheia.
Essencialmente, essa mudança afeta o ciclo de vida da atividade da mesma forma que ocorre quando o sistema notifica o app sobre a mudança da orientação retrato para paisagem no dispositivo, exceto que as dimensões do dispositivo são modificadas, em vez de simplesmente trocadas. Conforme discutido em Gerenciar alterações de configuração, sua atividade pode processar a mudança de configuração por conta própria ou permitir que o sistema destrua a atividade e a recrie 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 app demorar a desenhar nas áreas recém-expostas,
o sistema preencherá temporariamente essas áreas com a cor especificada pelo atributo
windowBackground
ou pelo atributo padrão de estilo
windowBackgroundFallback
.
Acesso exclusivo a recursos
Para ajudar a oferecer suporte ao recurso de retomadas múltiplas, use o novo callback do ciclo de vida,
onTopResumedActivityChanged()
.
Esse método é invocado quando uma atividade ganha ou perde a posição de principal atividade retomada. Isso é importante para saber quando uma atividade usa um recurso compartilhado de Singleton, como microfone ou câmera.
Kotlin
override fun onTopResumedActivityChanged(topResumed: Boolean) { if (topResumed) { // Top resumed activity // Can be a signal to re-acquire exclusive resources } else { // No longer the top resumed activity } }
Java
@Override public void onTopResumedActivityChanged(boolean topResumed) { if (topResumed) { // Top resumed activity // Can be a signal to re-acquire exclusive resources } else { // No longer the top resumed activity } }
Um app pode perder recursos por outros motivos, como a remoção de um hardware compartilhado.
Seja como for, é preciso que os apps tratem com eficiência os eventos e as mudanças de estado que afetam os recursos disponíveis.
Para apps que usam uma câmera,
o CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged()
fornece uma dica de que pode ser um bom momento para tentar acessar a
câmera. Esse método está disponível a partir do Android 10 (API de nível 29).
Lembre-se de que resizeableActivity=false
não garante o acesso exclusivo
à câmera, já que outros apps que usam a câmera podem ser abertos em outras
telas.
Figura 2. Câmera no modo de várias janelas.
Seu app não precisa liberar a câmera quando perder o foco. Por exemplo, é possível continuar com a visualização da câmera enquanto o usuário interage com o app retomado que foi colocado em foco mais recentemente. O aplicativo poderá continuar executando a câmera quando não for o de retomada principal, mas precisará gerenciar o caso de desconexão corretamente. Quando o app de retomada principal quiser usar a câmera, ele poderá abri-la, e seu app perderá o acesso. Seu app poderá reabrir a câmera quando for colocado em foco novamente.
Depois que um aplicativo receber uma chamada de retorno
CameraDevice.StateCallback#onDisconnected()
,
chamadas subsequentes na câmera do dispositivo acionarão
CameraAccessException
.
Várias telas
O Android 10 (API de nível 29) é compatível com atividades em telas secundárias. Se uma atividade estiver sendo executada em um dispositivo com várias telas, os usuários poderão mover a atividade de uma tela para outra. A retomada múltipla também se aplica a cenários com várias telas. Várias atividades podem receber entrada do usuário ao mesmo tempo.
Um app pode especificar em qual tela precisa ser executado quando for iniciado
ou quando criar outra atividade. Esse comportamento depende do modo de inicialização da atividade
definido no arquivo de manifesto, bem como das sinalizações de intents e opções definidas pela
entidade que está iniciando a atividade. Veja
ActivityOptions
para mais
detalhes.
Quando uma atividade é movida para uma tela secundária, ela pode passar por uma atualização
de contexto, redimensionamento de janela e mudanças de configuração e recursos. Se a
atividade processar a mudança de configuração, ela será notificada em
onConfigurationChanged()
.
Caso contrário, será reiniciada.
Uma atividade precisará verificar a tela atual em onCreate
e
onConfigurationChanged
se estiver processando a mudança de configuração. Certifique-se de
atualizar os recursos e layouts quando a tela mudar.
Se o modo de inicialização selecionado para uma atividade permitir várias instâncias, lembre-se de que a inicialização em uma tela secundária pode criar uma nova instância da atividade. As duas atividades serão retomadas ao mesmo tempo.
Figura 3. Várias instâncias de uma atividade em várias telas.
Para saber mais, leia sobre as APIs de várias telas que foram introduzidas no Android 8.0.
Atividade x contexto do app
Usar o contexto certo é fundamental quando se usa várias telas. Ao acessar recursos, o contexto da atividade (exibido) é diferente do contexto do app (que não é exibido).
O contexto da atividade contém informações sobre a tela e é sempre ajustado para a área da tela em que a atividade aparece. Isso permite que você tenha as informações corretas sobre as métricas de densidade ou janela de exibição do app no momento. É preciso usar sempre o contexto da atividade ou outro contexto baseado na IU para acessar informações sobre a janela ou tela atual. Isso também afeta algumas APIs do sistema que usam informações do contexto. Por exemplo, consulte Visão geral dos avisos.
A configuração da janela da atividade e da tela principal definem os recursos e o contexto. Veja a exibição atual da seguinte forma:
Kotlin
val activityDisplay = activity.getDisplay()
Java
Display activityDisplay = activity.getDisplay();
Veja as métricas atuais da janela de atividade:
Kotlin
val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()
Java
WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
Encontre o máximo de métricas da janela para a configuração atual do sistema:
Kotlin
val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()
Java
WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();
As métricas de janela máximas são para fazer cálculos, escolhas de layout ou
determinar o tamanho dos recursos a serem buscados antecipadamente. Se você as disponibilizar no
método onCreate()
, poderá tomar essas decisões antes da primeira transmissão
do layout. Essas métricas não devem ser usadas para dispor elementos de visualização específicos.
Em vez disso, use informações do objeto
Configuration
.
Corte da tela
Dispositivos dobráveis podem ter diferentes geometrias de corte quando dobrados e desdobrados. Para evitar problemas de corte, leia Práticas recomendadas para corte da tela.
Telas secundárias
Você pode acessar as telas disponíveis no
serviço do sistema
DisplayManager
:
Kotlin
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager val displays = displayManager.getDisplays()
Java
DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); Display[] displays = displayManager.getDisplays();
Use a classe Display
para ver
informações sobre uma tela específica, como o tamanho da tela ou
as sinalizações que indicam se
uma tela é segura. No entanto, não presuma que o tamanho da tela será
igual à área de exibição alocada ao aplicativo. Lembre-se de que,
no modo de várias janelas, o aplicativo ocupa uma parte da tela.
Determine se uma atividade pode ser iniciada em uma tela:
Kotlin
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)
Java
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);
Em seguida, inicie a atividade na tela:
Kotlin
val options = ActivityOptions.makeBasic() options.setLaunchDisplayId(targetDisplay.displayId) startActivity(intent, options.toBundle())
Java
ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(targetDisplay.displayId); startActivity(intent, options.toBundle());
Suporte a várias telas
O Android é compatível com várias telas para teclados de software, planos de fundo e telas de início.
Teclado de software
Um teclado poderá ser mostrado em uma tela secundária se a exibição estiver configurada como compatível com decorações do sistema. O editor de método de entrada será exibido automaticamente se um campo de texto solicitar entrada nessa tela.
Figura 4. Teclado em uma tela secundária.
Plano de fundo
No Android 10 (API de nível 29), as telas secundárias podem ter um plano de fundo. A
biblioteca cria uma instância separada de
WallpaperService.Engine
para cada tela. Certifique-se de que a superfície de cada mecanismo seja desenhada
de forma independente. Os desenvolvedores podem carregar recursos usando o contexto da tela em
WallpaperService.Engine#getDisplayContext()
.
Além disso, verifique se o arquivo WallpaperInfo.xml
é definido como
android:supportsMultipleDisplays="true"
.
Figura 5. Plano de fundo no smartphone e na tela secundária.
Telas de início
Uma nova categoria de filtro de intent, SECONDARY_HOME
, fornece uma atividade dedicada
para telas secundárias. Instâncias dessa atividade são usadas em todas as telas
compatíveis com decorações do sistema, uma para cada tela.
<activity>
...
<intent-filter>
<category android:name="android.intent.category.SECONDARY_HOME" />
...
</intent-filter>
</activity>
É necessário que a atividade tenha um modo de inicialização que não impeça várias instâncias
e que possa se adaptar a diferentes tamanhos de tela. Não é possível usar os modos de inicialização
singleInstance
ou singleTask
.
Por exemplo, a implementação do AOSP de
Launcher3
é compatível com uma atividade SECONDARY_HOME
.
Figura 6. Tela de início com Material Design em um smartphone.
Figura 7. Tela de início com Material Design em uma tela secundária.
Métricas de janela
O Android 11 (API de nível 30) introduziu os métodos
WindowManager
a seguir para
fornecer os limites dos apps em execução no modo de várias janelas:
getCurrentWindowMetrics()
: retorna um objetoWindowMetrics
para o estado atual do janelamento do sistema.getMaximumWindowMetrics()
: retornaWindowMetrics
para o maior estado de janelamento do sistema.
Os métodos da biblioteca WindowManager do Jetpack
computeCurrentWindowMetrics()
e
computeMaximumWindowMetrics()
oferecem uma funcionalidade semelhante, respectivamente, mas com compatibilidade com versões anteriores à
API de nível 14.
Métodos obsoletos
Os métodos Display
getSize()
e
getMetrics()
foram descontinuados na API de nível 30 em favor dos novos métodos WindowManager
.
No Android 12 (API de nível 31), foram descontinuados os métodos Display
getRealSize()
e
getRealMetrics()
,
e o comportamento deles foi atualizado para corresponder mais ao comportamento de
getMaximumWindowMetrics()
.
Configuração do modo de várias janelas
Se o seu app for direcionado ao Android 7.0 (API de nível 24) ou versões mais recentes, será possível configurar
como e se as atividades dele 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="true"
,
todas as atividades na pilha de tarefas serão redimensionáveis. Em alguns dispositivos maiores,
como os Chromebooks, seu app pode ser executado em uma janela redimensionável, mesmo se você
especificar android:resizeableActivity="false"
. Se isso corromper seu app, você poderá usar
filtros para restringir a disponibilidade dele
nesses dispositivos.
Observação: se você criar um app com várias orientações direcionado à API de nível 23 ou anterior e o usuário usá-lo no modo de várias janelas, o sistema forçará o redimensionamento do app. O sistema exibe uma caixa de diálogo avisando o usuário que o app pode se comportar de forma inesperada. O sistema não redimensiona apps de orientação fixa. Se o usuário tentar abrir um app desse tipo no modo de várias janelas, ele ocupará toda a tela.
O Android 12 (API de nível 31) assume como padrão o modo de várias janelas. Em telas grandes
(com 600 dp ou mais), todos os apps são executados no modo de várias janelas, seja qual for a configuração
deles. Em telas pequenas, o sistema verifica a
minWidth
,
minHeight
e
resizeableActivity
para determinar se a atividade pode ser executada no modo de várias janelas.
resizeableActivity
Defina esse atributo no elemento
<activity>
ou
<application>
do seu manifesto para
ativar ou desativar a exibição em várias janelas na API de nível 30 e anteriores:
<application android:name=".MyActivity" android:resizeableActivity=["true" | "false"] />
Se esse atributo for definido como true, a atividade poderá ser inicializada nos modos de tela dividida e formato livre. Se o atributo for definido como false, a atividade não será compatível com o modo de várias janelas. Se o valor for false e o usuário tentar iniciar a atividade no modo de várias janelas, a atividade usará o modo tela cheia.
Se o app for destinado à API de nível 24 ou mais recente, mas você não especificar um valor para esse atributo, ele será definido como true.
Se o app for direcionado à API de nível 31 ou mais recente, esse atributo funcionará de forma diferente em telas pequenas e grandes:
- Telas grandes (com 600 dp ou mais): todos os apps são compatíveis com o modo de várias janelas. O
atributo indica se uma atividade pode ser redimensionada. Se
resizeableActivity="false"
, o app será colocado em modo de compatibilidade quando necessário para atender às dimensões de exibição. - Telas pequenas (com menos de 600 dp): se
resizeableActivity="true"
e a largura e altura mínimas da atividade estiverem dentro dos requisitos de várias janelas, a atividade será compatível com o modo de várias janelas. SeresizeableActivity="false"
, a atividade não será compatível com o modo de várias janelas, independentemente da largura e altura mínimas da atividade.
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.
<activity android:name=".MyActivity" android:supportsPictureInPicture=["true" | "false"] />
Observação: se supportsPictureInPicture="true"
, você
precisará definir o atributo android:configChanges
para permitir que sua
atividade processe mudanças de configuração. Consulte
Compatibilidade com picture-in-picture.
configChanges
Para processar mudanças de configuração de várias janelas, por exemplo, quando um usuário
redimensiona uma janela, adicione o
atributo
android:configChanges
ao nó
<activity>
do manifesto do app com
pelo menos os seguintes valores:
<activity android:name=".MyActivity" android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation" />
Após a adição de
android:configChanges
,
sua atividade e seus fragmentos recebem um callback para
onConfigurationChanged()
em vez de serem destruídos e recriados. É possível, então, atualizar manualmente suas
visualizações, recarregar recursos e executar outras operações, conforme o necessário.
<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 formato livre.
-
android:defaultHeight
- Altura padrão da atividade quando iniciada no modo de formato livre.
-
android:gravity
-
Posicionamento inicial da atividade quando iniciada no modo de formato livre. Consulte a referência de
Gravity
para verificar os valores adequados. -
android:minHeight
,android:minWidth
- Indicam a altura e largura mínimas para a atividade nos modos de tela dividida e formato 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.
O código a seguir mostra como especificar um tamanho e um local padrão para a atividade, além do tamanho mínimo quando a atividade é exibida no modo de formato livre:
<activity android:name=".MyActivity"> <layout android:defaultHeight="500dp" android:defaultWidth="600dp" android:gravity="top|end" android:minHeight="450dp" android:minWidth="300dp" /> </activity>
Modo de várias janelas no ambiente de execução
A partir do Android 7.0, o sistema oferece funcionalidade de compatibilidade com apps 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, porque não fazem sentido para uma atividade que pode estar compartilhando a tela do dispositivo com outras atividades ou apps.
Algumas opções de personalização de IU do sistema estão desativadas. Por exemplo, os apps não poderão ocultar a barra de status se estiverem sendo executados no modo de várias janelas. Consulte Controlar a visibilidade da IU do sistema.
O sistema ignora as mudanças no
atributo
android:screenOrientation
.
Callbacks e consultas no modo de várias janelas
A classe Activity
oferece os
seguintes métodos para suporte à exibição em várias janelas:
-
isInMultiWindowMode()
- Indica se a atividade está no modo de várias janelas.
-
isInPictureInPictureMode()
- Indica 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 “verdadeiro”,myActivity.isInMultiWindowMode()
também retornará “verdadeiro”. -
onMultiWindowModeChanged()
- O sistema chama esse método sempre que a atividade entra ou sai do modo de várias janelas. O sistema transmitirá o valor true ao método 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 transmitirá o valor true ao método 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()
.
Modo picture-in-picture
Para colocar uma atividade no modo picture-in-picture, chame
enterPictureInPictureMode()
.
Esse método não terá efeito se o dispositivo não for compatível com o modo
picture-in-picture. Para ver mais informações, consulte
Compatibilidade com picture-in-picture.
Novas atividades no modo de várias janelas
Quando você inicia uma nova atividade, pode indicar que ela
será exibida adjacente à atual, se possível. Use a sinalização de intent
FLAG_ACTIVITY_LAUNCH_ADJACENT
, que instrui o sistema a tentar
criar a nova atividade em uma janela adjacente. Assim, as duas atividades compartilham a
tela. O sistema faz o possível, mas não é garantido que isso
aconteça.
Se um dispositivo estiver no modo de formato 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.
Na API de nível 30 ou anterior, se você iniciar uma atividade em uma pilha de tarefas, a atividade substituirá a que está na tela, herdando todas as propriedades de várias janelas. Se você quiser iniciar a nova atividade como uma janela separada no modo de várias janelas, inicie-a em uma nova pilha de tarefas.
O Android 12 (API de nível 31) permite que os apps dividam a janela de tarefas de um app entre várias atividades. Para determinar como o app exibe as atividades (tela cheia, lado a lado ou empilhada), crie um arquivo de configuração XML ou faça chamadas da API WindowManager do Jetpack.
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 só podiam
arrastar e soltar dados em uma única atividade. Para adicionar rapidamente compatibilidade com
conteúdo arrastado e solto em widgets TextView
editáveis, consulte a interface
OnReceiveContentListener
. Para oferecer compatibilidade abrangente com o recurso de arrastar e soltar, como ativar o recurso de arrastar do conteúdo do app, consulte o tópico
Arrastar e soltar.
As classes e os métodos importantes para implementar a ação de arrastar e soltar incluem:
-
ClipData
- Representação dos dados na área de transferência. Referencia os dados a serem transferidos pela operação de arrastar e soltar.
-
DragAndDropPermissions
- É o objeto token responsável por especificar as permissões concedidas ao app que recebe uma ação de soltar.
-
DragAndDropPermissions.release()
-
Libera as permissões necessárias para acessar os dados no URI de conteúdo fornecido
no
ClipData
. Se você não chamar esse método, as permissões serão liberadas automaticamente quando a atividade contida for destruída. -
View.startDragAndDrop()
-
Para ativar o recurso de arrastar e soltar entre atividades, transmita a sinalização
DRAG_FLAG_GLOBAL
. Se você precisar conceder permissões de URI à atividade de destino, transmitaDRAG_FLAG_GLOBAL_URI_READ
ouDRAG_FLAG_GLOBAL_URI_WRITE
. -
View.cancelDragAndDrop()
- Cancela uma operação de arrastar em andamento. Só pode ser chamado pelo app que originou a operação de arrastar.
-
View.updateDragShadow()
- Substitui a ação de arrastar para uma operação de arrastar em andamento. Só pode ser chamado pelo app que originou a operação de arrastar.
-
Activity.requestDragAndDropPermissions()
-
Solicita as permissões dos URIs de conteúdo transmitidos com o
ClipData
contido em umDragEvent
.
Várias instâncias
Cada atividade raiz tem uma tarefa própria, que é executada em um processo separado
e exibida na própria janela. Para iniciar uma nova instância do seu app em uma janela separada, inicie novas atividades com a
sinalização FLAG_ACTIVITY_NEW_TASK
.
Você pode combinar isso com alguns dos atributos de várias janelas para
solicitar um local específico para a nova janela. Por exemplo, um aplicativo de compras
pode exibir várias janelas para comparar produtos.
O Android 12 (API de nível 31) permite iniciar duas instâncias de uma atividade lado a lado na mesma janela de tarefas.
Não confunda várias instâncias com um layout de vários painéis, como um layout de
lista/detalhes que usa
SlidingPaneLayout
, que
é executado em uma única janela.
Quando várias instâncias estão em execução em janelas separadas em um dispositivo dobrável, uma ou mais instâncias poderão ser enviadas para o segundo plano se a posição mudar. Por exemplo, suponha que um dispositivo não esteja dobrado e tenha duas instâncias de app em execução em duas janelas em ambos os lados. Se o dispositivo estiver dobrado, uma das instâncias poderá ser encerrada em vez de tentar encaixar as janelas de ambas as instâncias em uma tela menor.
Verificação no modo de várias janelas
Mesmo que o app não seja destinado à API de nível 24 ou mais recente, é importante verificar como ele se comporta no modo de várias janelas, porque um usuário pode tentar iniciá-lo nesse modo em um dispositivo com o Android 7.0 ou mais recente.
Configurar um dispositivo de teste
Se um dispositivo usar o Android 7.0 ou mais recente, ele será automaticamente compatível com o modo de tela dividida.
Caso seu app seja direcionado à API de nível 23 ou anterior
Quando os usuários tentam usar o app no modo de várias janelas, o sistema força o redimensionamento do app, a menos que ele declare uma orientação fixa.
Se o app não declarar uma orientação fixa, inicie-o em um dispositivo com o Android 7.0 ou mais recente e tente colocar o app no modo de tela dividida. Verifique se a experiência do usuário é aceitável quando o redimensionamento do app é forçado.
Se o app declarar uma orientação fixa, tente colocá-lo no modo de várias janelas. Ao fazer isso, verifique se ele continua no modo de tela cheia.
Caso seu app seja direcionado a APIs de nível 24 a 30
Se o app for direcionado a APIs de nível 24 a 30 e não desativar a compatibilidade com várias janelas, verifique o seguinte comportamento nos modos de tela dividida e formato livre:
- Toque no botão "Recentes" e mantenha-o pressionado para iniciar o app no modo de tela cheia e mudar para o modo de várias janelas. Verifique se o app alterna corretamente.
- Inicie o app diretamente no modo de várias janelas e verifique se a inicialização ocorre da forma correta. Você pode iniciar um app no modo de várias janelas pressionando o botão "Recentes" e, em seguida, mantendo pressionada a barra de título do app e arrastando-o a uma das áreas destacadas na tela.
- Para redimensionar o app no modo de tela dividida, arraste o divisor de tela. Verifique se o app é redimensionado sem falhar e se os elementos de IU necessários estão visíveis.
- Se você especificou dimensões mínimas para o app, tente redimensioná-lo abaixo dessas dimensões. Verifique se não é possível redimensionar o app para um tamanho menor que o mínimo especificado.
- Em todos os testes, verifique se o desempenho do app é aceitável. Por exemplo, verifique se há uma demora muito grande para atualizar a IU após o redimensionamento do app.
Caso seu app seja direcionado à API de nível 31 ou mais recente
Se o app for direcionado à API de nível 31 ou mais recente, e a largura e altura mínimas da atividade principal forem menores ou iguais às respectivas dimensões da área de exibição disponível, verifique todos os comportamentos listados para APIs de nível 24 a 30.
Observação: você pode determinar programaticamente se o app está no
modo de várias janelas, verificando o valor de retorno de
Activity#isInMultiWindowMode()
.
Lista de verificação de teste
Para verificar o desempenho do app no modo de várias janelas, realize as operações a seguir. Tente executar estas operações nos modos de tela dividida e de formato livre, exceto quando houver instruções diferentes.
- Entre e saia do modo de várias janelas.
- Alterne do seu app para outro e verifique se ele se comporta corretamente enquanto visível, mas não ativo. Por exemplo, se o app estiver reproduzindo vídeo, verifique se a reprodução não é interrompida quando o usuário interage com outro app.
- No modo de tela dividida, mova o divisor de tela para aumentar e reduzir o tamanho do app. Tente executar essas operações nas configurações lado a lado e um acima do outro. Verifique se o app 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 app não falha nem apresenta vazamentos de memória. O Memory Profiler do Android Studio oferece informações sobre o uso da memória do app. Consulte Inspecionar o uso de memória do seu app com o Memory Profiler.
- Use o app normalmente em configurações diferentes de janela e verifique se ele se comporta corretamente. Verifique se o texto é legível e se os elementos da IU não ficam pequenos demais para a interação.
Se você desativou a compatibilidade com o modo de várias janelas
Nas APIs de nível 24 a 30, se você desativou a compatibilidade com várias janelas ao definir
android:resizeableActivity="false"
, inicie o app em
um dispositivo com o Android 7.0 a 11 e tente colocá-lo na
modos de tela dividida e formato livre. Ao fazer isso, verifique se ele continua
no modo de tela cheia.
Outros recursos
Para mais informações sobre a compatibilidade com várias janelas no Android, consulte:
- Cinco dicas para preparar o modo de várias janelas no Android N (link em inglês)
- Amostra do Android MultiWindowPlayground (link em inglês)