Com o modo janela para computador, os usuários podem executar vários apps simultaneamente em janelas redimensionáveis para ter uma experiência versátil, semelhante à de um computador.
Na figura 1, é possível ver a organização da tela com o recurso de janelas do computador ativado. Observações:
- Os usuários podem executar vários apps lado a lado simultaneamente.
- A barra de tarefas fica em uma posição fixa na parte de baixo da tela, mostrando os apps em execução. Os usuários podem fixar apps para acesso rápido.
- Uma nova barra de cabeçalho personalizável decora a parte de cima de cada janela com controles como minimizar e maximizar.
Por padrão, os apps são abertos em tela cheia nos tablets Android. Para abrir um app no modo janela para computador, pressione e mantenha pressionada a alça da janela na parte de cima da tela e arraste a alça na interface, conforme mostrado na Figura 2.
Quando um app está aberto no janelamento para computadores, outros apps também são abertos em janelas de computador.
Os usuários também podem invocar o redimensionamento de janelas da área de trabalho no menu que aparece abaixo da alça da janela ao tocar ou clicar nela ou usar o atalho de teclado tecla Meta (Windows, Command ou Pesquisa) + Ctrl + Seta para baixo.
Para sair do modo de janelas na área de trabalho, os usuários precisam fechar todas as janelas ativas ou arrastar a alça da janela na parte de cima de uma janela da área de trabalho até a parte de cima da tela. O atalho de teclado Meta + H também sai do modo janela para computador e executa os apps em tela cheia novamente.
Para voltar ao modo de janelas da área de trabalho, toque ou clique no bloco do espaço da área de trabalho na tela "Recentes".
Redimensionamento e modo de compatibilidade
No sistema de janelas para computador, os apps com orientação bloqueada podem ser redimensionados livremente. Isso significa que, mesmo que uma atividade esteja bloqueada na orientação retrato, os usuários ainda podem redimensionar o app para uma janela de orientação paisagem.
Os apps declarados como não redimensionáveis (ou seja,
resizeableActivity = false)
têm a interface dimensionada, mantendo a mesma proporção.
Os apps de câmera que bloqueiam a orientação ou são declarados como não redimensionáveis têm um tratamento especial para os visores: a janela é totalmente redimensionável, mas o visor mantém a mesma proporção. Ao presumir que os apps sempre são executados na vertical ou horizontal, eles codificam ou fazem outras suposições que levam a cálculos incorretos da orientação ou proporção da imagem capturada ou de visualização, resultando em imagens esticadas, laterais ou de cabeça para baixo.
Enquanto os apps não estiverem prontos para implementar visores de câmera totalmente responsivos, o tratamento especial vai oferecer uma experiência do usuário mais básica que mitiga os efeitos que suposições erradas podem causar.
Para saber mais sobre o modo de compatibilidade para apps de câmera, consulte Modo de compatibilidade do dispositivo.
Encaixes de cabeçalho personalizáveis
Todos os apps executados em janelas de computador têm uma barra de cabeçalho, mesmo no
modo imersivo.
Verifique se o conteúdo do app não está sendo ocultado pela barra de cabeçalho.
A barra de cabeçalho é um tipo de encarte de barra de legenda:
WindowInsets.Companion.captionBar();
em visualizações, WindowInsets.Type.captionBar(),
que faz parte das barras de sistema.
Saiba mais sobre como processar encartes em Mostrar conteúdo de ponta a ponta no app e processar encartes de janela no Compose.
A barra de cabeçalho também pode ser personalizada. O Android 15 introduziu o tipo de aparência
APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND para tornar
a barra de cabeçalho transparente e permitir que os apps mostrem conteúdo personalizado dentro
dela.
Os apps passam a ser responsáveis por estilizar a parte de cima do conteúdo para parecer a barra de legenda (segundo plano, conteúdo personalizado etc.), com exceção dos elementos de legenda do sistema (botões de fechar e maximizar), que são mostrados pelo sistema na barra de legenda transparente na parte de cima do app.
Os apps podem alternar a aparência dos elementos do sistema dentro da legenda para
temas claros e escuros usando APPEARANCE_LIGHT_CAPTION_BARS,
de maneira semelhante à alternância da barra de status e da barra de navegação.
O Android 15 também introduziu o método WindowInsets#getBoundingRects()
que permite que os apps façam a introspecção dos encartes da barra de legenda com mais detalhes. Os apps podem
diferenciar entre áreas em que o sistema desenha elementos do sistema e
áreas não utilizadas em que os apps podem colocar conteúdo personalizado sem sobrepor elementos do
sistema.
A lista de objetos Rect retornados pela API indica regiões do sistema que devem ser evitadas. O espaço restante (calculado subtraindo os retângulos dos encartes da barra de legenda) é onde o app pode desenhar sem sobrepor elementos do sistema e com a capacidade de receber entrada.
Para definir retângulos de exclusão de gestos do sistema para um cabeçalho personalizado, implemente o seguinte na sua visualização ou elemento combinável:
// In a custom View's onLayout or a similar lifecycle method
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (changed) {
// Calculate the height of your custom header
val customHeaderHeight = 100 // Replace with your actual header height in pixels
// Create a Rect covering your custom header area
val exclusionRect = Rect(0, 0, width, customHeaderHeight)
// Set the exclusion rects for the system
systemGestureExclusionRects = listOf(exclusionRect)
}
}
Suporte a multitarefas e várias instâncias
A multitarefa é a base do modo janela para computador, e permitir várias instâncias do seu app pode aumentar muito a produtividade dos usuários.
O Android 15 introduz
PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI,
que os apps podem definir para especificar que a interface do sistema precisa ser mostrada para que o app
possa ser iniciado como várias instâncias.
Você pode declarar PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI no
AndroidManifest.xml do app dentro da tag <activity>:
<activity
android:name=".MyActivity"
android:exported="true"
android:resizeableActivity="true">
<meta-data
android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
android:value="true" />
</activity>
Gerenciar instâncias de apps com gestos de arrastar
No modo de várias janelas, os usuários podem iniciar uma nova instância de app arrastando um elemento de visualização para fora da janela do app. Os usuários também podem mover elementos entre instâncias do mesmo app.
O Android 15 apresenta duas flags para personalizar o comportamento de arrastar:
DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: indica que uma ação de arrastar sem tratamento precisa ser delegada ao sistema para ser iniciada se nenhuma janela visível processar a ação de soltar. Ao usar essa flag, o caller precisa fornecerClipDatacom umClipData.Itemque contenha umIntentSenderimutável para uma atividade a ser iniciada (consulteClipData.Item.Builder#setIntentSender()). O sistema pode iniciar ou não a intent com base em fatores como o tamanho atual da tela ou o modo de janela. Se o sistema não iniciar a intent, ela será cancelada pelo fluxo normal de arrastar.DRAG_FLAG_GLOBAL_SAME_APPLICATION: indica que uma operação de arrastar pode cruzar limites de janela (para várias instâncias do mesmo aplicativo).Quando [
startDragAndDrop()][20] é chamado com essa flag definida, apenas janelas visíveis pertencentes ao mesmo aplicativo podem participar da operação de arrastar e receber o conteúdo arrastado.
O exemplo a seguir demonstra como usar essas flags com
startDragAndDrop():
// Assuming 'view' is the View that initiates the drag
view.setOnLongClickListener {
// Create an IntentSender for the activity you want to launch
val launchIntent = Intent(view.context, NewInstanceActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
view.context,
0,
launchIntent,
PendingIntent.FLAG_IMMUTABLE // Ensure the PendingIntent is immutable
)
// Build the ClipData.Item with the IntentSender
val item = ClipData.Item.Builder()
.setIntentSender(pendingIntent.intentSender)
.build()
// Create ClipData with a simple description and the item
val dragData = ClipData(
ClipDescription("New Instance Drag", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN)),
item
)
// Combine the drag flags
val dragFlags = View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG or
View.DRAG_FLAG_GLOBAL_SAME_APPLICATION
// Start the drag operation
view.startDragAndDrop(
dragData, // The ClipData to drag
View.DragShadowBuilder(view), // A visual representation of the dragged item
null, // Local state object (not used here)
dragFlags // The drag flags
)
true // Indicate that the long click was consumed
}
Otimizações adicionais
Personalize as inicializações de apps e faça a transição de apps do modo janela para computador para tela cheia.
Especificar tamanho e posição padrão
Nem todos os apps, mesmo que redimensionáveis, precisam de uma janela grande para oferecer valor ao usuário.
Use o método ActivityOptions#setLaunchBounds()
para especificar um tamanho e uma posição padrão quando uma atividade é iniciada.
Confira um exemplo de como definir limites de inicialização para uma atividade:
val options = ActivityOptions.makeBasic()
// Define the desired launch bounds (left, top, right, bottom in pixels)
val launchBounds = Rect(100, 100, 700, 600) // Example: 600x500 window at (100,100)
// Apply the launch bounds to the ActivityOptions
options.setLaunchBounds(launchBounds)
// Start the activity with the specified options
val intent = Intent(this, MyActivity::class.java)
startActivity(intent, options.toBundle())
Entrar no modo de tela cheia no espaço de trabalho
Os apps podem entrar em tela cheia chamando Activity#requestFullScreenMode().
O método mostra o app em tela cheia diretamente do redimensionamento da janela do computador.
Para solicitar o modo de tela cheia de uma atividade, use o seguinte código:
// In an Activity
fun enterFullScreen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 15 (U)
requestFullScreenMode()
}
}