El modo de ventanas de escritorio permite que los usuarios ejecuten varias apps simultáneamente en ventanas de apps redimensionables para brindar una experiencia versátil similar a la de una computadora de escritorio.
En la figura 1, puedes ver la organización de la pantalla con la función de ventanas de escritorio habilitada. Información que debes tener en cuenta:
- Los usuarios pueden ejecutar varias apps una al lado de la otra de forma simultánea.
- La barra de tareas se encuentra en una posición fija en la parte inferior de la pantalla y muestra las apps en ejecución. Los usuarios pueden fijar apps para acceder a ellas rápidamente.
- La nueva barra de encabezado personalizable decora la parte superior de cada ventana con controles como minimizar y maximizar.
De forma predeterminada, las apps se abren en pantalla completa en las tablets Android. Para iniciar una app en ventanas de escritorio, mantén presionado el controlador de la ventana en la parte superior de la pantalla y arrástralo dentro de la IU, como se muestra en la figura 2.
Cuando una app se abre en la renderización en ventanas de escritorio, las demás apps también se abren en ventanas de escritorio.
Los usuarios también pueden invocar la función de ventanas de escritorio desde el menú que aparece debajo del controlador de la ventana cuando presionan o hacen clic en el controlador, o bien usan la combinación de teclas tecla Meta (Windows, Comando o Búsqueda) + Ctrl + flecha hacia abajo.
Para salir del modo de ventanas de escritorio, los usuarios deben cerrar todas las ventanas activas o tomar el controlador de la ventana en la parte superior de una ventana de escritorio y arrastrar la app a la parte superior de la pantalla. La combinación de teclas Meta + H también cierra las ventanas de escritorio y vuelve a ejecutar las apps en pantalla completa.
Para volver a la ventana de escritorio, presiona o haz clic en el mosaico del espacio de escritorio en la pantalla Recientes.
Modo de compatibilidad y cambio de tamaño
En el sistema de ventanas de escritorio, las apps con orientación bloqueada se pueden redimensionar libremente. Esto significa que, incluso si una actividad está bloqueada en orientación vertical, los usuarios pueden cambiar el tamaño de la app a una ventana de orientación horizontal.
Las apps declaradas como no redimensionables (es decir, resizeableActivity = false) tienen su IU ajustada mientras mantienen la misma relación de aspecto.
Las apps de cámara que bloquean la orientación o se declaran como no redimensionables tienen un tratamiento especial para sus visores de cámara: la ventana es completamente redimensionable, pero el visor mantiene la misma relación de aspecto. Si se supone que las apps siempre se ejecutan en orientación vertical u horizontal, las apps codifican de forma rígida o, de otro modo, realizan suposiciones que conducen a cálculos incorrectos de la orientación o la relación de aspecto de la vista previa o la imagen capturada, lo que genera imágenes estiradas, laterales o invertidas.
Hasta que las apps estén listas para implementar visores de cámara completamente responsivos, el tratamiento especial proporcionará una experiencia del usuario más básica que mitigue los efectos que puedan causar las suposiciones incorrectas.
Para obtener más información sobre el modo de compatibilidad de las apps de cámara, consulta Modo de compatibilidad del dispositivo.
Inserciones de encabezado personalizables
Todas las apps que se ejecutan en ventanas de escritorio tienen una barra de encabezado, incluso en el modo envolvente.
Verifica que la barra de encabezado no oculte el contenido de tu app.
La barra de encabezado es un tipo de inserción de barra de subtítulos:
WindowInsets.Companion.captionBar();
en las vistas, WindowInsets.Type.captionBar(),
que forma parte de las barras del sistema.
Puedes obtener más información para controlar las inserciones en Cómo mostrar el contenido de borde a borde en tu app y controlar las inserciones de ventana en Compose.
La barra de encabezado también se puede personalizar. Android 15 introdujo el tipo de apariencia APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND para que la barra de encabezado sea transparente y permita que las apps dibujen contenido personalizado dentro de ella.
Luego, las apps se vuelven responsables de aplicar el diseño a la parte superior de su contenido para que se vea como la barra de leyendas (fondo, contenido personalizado, etcétera), con la excepción de los elementos de leyendas del sistema (botones de cerrar y maximizar), que el sistema dibuja en la barra de leyendas transparente en la parte superior de la app.
Las apps pueden activar o desactivar la apariencia de los elementos del sistema dentro del subtítulo para los temas claro y oscuro con APPEARANCE_LIGHT_CAPTION_BARS, de manera similar a como se activa o desactiva la barra de estado y la barra de navegación.
Android 15 también introdujo el método WindowInsets#getBoundingRects(), que permite que las apps inspeccionen las inserciones de la barra de leyendas con más detalle. Las apps pueden diferenciar entre las áreas en las que el sistema dibuja elementos del sistema y las áreas no utilizadas en las que las apps pueden colocar contenido personalizado sin superponer elementos del sistema.
La lista de objetos Rect que devuelve la API indica las regiones del sistema que se deben evitar. El espacio restante (que se calcula restando los rectángulos de los Insets de la barra de título) es donde la app puede dibujar sin superponerse con los elementos del sistema y con la capacidad de recibir entrada.
Para establecer rectángulos de exclusión de gestos del sistema para un encabezado personalizado, implementa lo siguiente en tu vista o elemento componible:
// 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)
}
}
Compatibilidad con instancias y tareas múltiples
La multitarea es la base de las ventanas de escritorio, y permitir varias instancias de tu app puede aumentar considerablemente la productividad de los usuarios.
Android 15 introduce PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, que las apps pueden establecer para especificar que se debe mostrar la IU del sistema para que la app permita que se inicie como varias instancias.
Puedes declarar PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI en el AndroidManifest.xml de tu app dentro de la etiqueta <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>
Administra instancias de apps con gestos de arrastre
En el modo multiventana, los usuarios pueden iniciar una nueva instancia de la app arrastrando un elemento de vista fuera de la ventana de la app. Los usuarios también pueden mover elementos entre instancias de la misma app.
Android 15 introduce dos marcas para personalizar el comportamiento de arrastre:
DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: Indica que un arrastre no controlado se debe delegar al sistema para que se inicie si ninguna ventana visible controla la acción de soltar. Cuando se usa esta marca, el llamador debe proporcionarClipDatacon unClipData.Itemque contenga unIntentSenderinmutable para una actividad que se lanzará (consultaClipData.Item.Builder#setIntentSender()). El sistema puede lanzar el intent o no según factores como el tamaño de pantalla o el modo de ventanas actuales. Si el sistema no inicia el intent, este se cancela a través del flujo de arrastre normal.DRAG_FLAG_GLOBAL_SAME_APPLICATION: Indica que una operación de arrastre puede cruzar los límites de la ventana (para varias instancias de la misma aplicación).Cuando se llama a [
startDragAndDrop()][20] con este parámetro de configuración, solo las ventanas visibles que pertenecen a la misma aplicación pueden participar en la operación de arrastre y recibir el contenido arrastrado.
En el siguiente ejemplo, se muestra cómo usar estas marcas con 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
}
Optimizaciones adicionales
Personaliza los inicios de apps y la transición de apps de ventanas en computadoras a pantalla completa.
Cómo especificar el tamaño y la posición predeterminados
No todas las apps, incluso si se pueden cambiar de tamaño, necesitan una ventana grande para ofrecer valor al usuario.
Puedes usar el método ActivityOptions#setLaunchBounds() para especificar un tamaño y una posición predeterminados cuando se inicia una actividad.
A continuación, se muestra un ejemplo de cómo establecer límites de inicio para una actividad:
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())
Cómo ingresar a pantalla completa desde el espacio de trabajo
Las apps pueden pasar a pantalla completa llamando a Activity#requestFullScreenMode().
El método muestra la app en pantalla completa directamente desde la ventana del escritorio.
Para solicitar el modo de pantalla completa desde una actividad, usa el siguiente código:
// In an Activity
fun enterFullScreen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 15 (U)
requestFullScreenMode()
}
}