Le fenêtrage du bureau permet aux utilisateurs d'exécuter plusieurs applications simultanément dans des fenêtres d'application redimensionnables pour une expérience polyvalente semblable à celle d'un ordinateur.
La figure 1 illustre l'organisation de l'écran lorsque le fenêtrage du bureau est activé. Points à noter :
- Les utilisateurs peuvent exécuter plusieurs applications côte à côte simultanément.
- La barre des tâches est en position fixe en bas de l'écran et affiche les applications en cours d'exécution. Les utilisateurs peuvent épingler des applications pour y accéder rapidement.
- Une nouvelle barre d'en-tête personnalisable décore le haut de chaque fenêtre avec des commandes telles que "Réduire" et "Agrandir".
Par défaut, les applications s'ouvrent en plein écran sur les tablettes Android. Pour lancer une application en mode fenêtrage du bureau, appuyez de manière prolongée sur la poignée de la fenêtre en haut de l'écran et faites-la glisser dans l'UI, comme illustré sur la figure 2.
Lorsqu'une application est ouverte dans le fenêtrage de bureau, les autres applications s'ouvrent également dans des fenêtres de bureau.
Les utilisateurs peuvent également appeler le fenêtrage du bureau à partir du menu qui s'affiche sous le handle de la fenêtre lorsqu'ils appuient ou cliquent sur le handle, ou en utilisant le raccourci clavier Touche Meta (Windows, Commande ou Recherche) + Ctrl + Flèche vers le bas.
Les utilisateurs quittent le mode fenêtré sur ordinateur en fermant toutes les fenêtres actives ou en saisissant le handle de fenêtre en haut d'une fenêtre de bureau et en faisant glisser l'application vers le haut de l'écran. Le raccourci clavier Meta+H permet également de quitter le mode fenêtré et d'exécuter à nouveau les applications en plein écran.
Pour revenir à l'affichage des fenêtres sur le bureau, appuyez ou cliquez sur la vignette de l'espace de bureau dans l'écran "Récents".
Redimensionnement et mode de compatibilité
Dans le fenêtrage de bureau, les applications dont l'orientation est verrouillée sont librement redimensionnables. Cela signifie que même si une activité est verrouillée en orientation portrait, les utilisateurs peuvent toujours redimensionner l'application en une fenêtre d'orientation paysage.
Les applications déclarées comme non redimensionnables (c'est-à-dire resizeableActivity = false) voient leur UI mise à l'échelle tout en conservant les mêmes proportions.
Les applications d'appareil photo qui verrouillent l'orientation ou sont déclarées comme non redimensionnables bénéficient d'un traitement spécial pour leur viseur : la fenêtre est entièrement redimensionnable, mais le viseur conserve le même format. En supposant que les applications s'exécutent toujours en mode Portrait ou Paysage, elles codent en dur ou font des hypothèses qui entraînent des erreurs de calcul de l'orientation ou du format de l'image prévisualisée ou capturée, ce qui donne des images étirées, de travers ou à l'envers.
Tant que les applications ne sont pas prêtes à implémenter des viseurs d'appareil photo entièrement responsifs, le traitement spécial offre une expérience utilisateur plus basique qui atténue les effets que de mauvaises hypothèses peuvent entraîner.
Pour en savoir plus sur le mode de compatibilité des applications de caméras, consultez Mode de compatibilité avec les appareils.
Encarts d'en-tête personnalisables
Toutes les applications s'exécutant dans un système de fenêtres de bureau disposent d'une barre d'en-tête, même en mode immersif.
Vérifiez que le contenu de votre application n'est pas masqué par la barre d'en-tête.
La barre d'en-tête est un type d'encart de barre de légende :
WindowInsets.Companion.captionBar();
dans les vues, WindowInsets.Type.captionBar(),
qui fait partie des barres système.
Pour en savoir plus sur la gestion des encarts, consultez Afficher le contenu bord à bord dans votre application et gérer les encarts de fenêtre dans Compose.
La barre d'en-tête est également personnalisable. Android 15 a introduit le type d'apparence APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND pour rendre la barre d'en-tête transparente et permettre aux applications de dessiner du contenu personnalisé à l'intérieur de la barre d'en-tête.
Les applications sont alors responsables de la mise en forme de la partie supérieure de leur contenu pour qu'elle ressemble à la barre de légende (arrière-plan, contenu personnalisé, etc.), à l'exception des éléments de légende système (boutons de fermeture et d'agrandissement), qui sont dessinés par le système sur la barre de légende transparente au-dessus de l'application.
Les applications peuvent activer ou désactiver l'apparence des éléments système dans la légende pour les thèmes clair et sombre à l'aide de APPEARANCE_LIGHT_CAPTION_BARS, de la même manière que la barre d'état et la barre de navigation.
Android 15 a également introduit la méthode WindowInsets#getBoundingRects(), qui permet aux applications d'inspecter plus en détail les encarts de la barre de légende. Les applications peuvent faire la différence entre les zones où le système dessine des éléments système et les zones inutilisées où les applications peuvent placer du contenu personnalisé sans chevaucher les éléments système.
La liste des objets Rect renvoyée par l'API indique les régions système à éviter. L'espace restant (calculé en soustrayant les rectangles des Insets de la barre de légende) est l'endroit où l'application peut dessiner sans chevaucher les éléments système et avec la possibilité de recevoir des entrées.
Pour définir des rectangles d'exclusion des gestes système pour un en-tête personnalisé, implémentez ce qui suit dans votre vue ou composable :
// 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)
}
}
Compatibilité avec le multitâche et les instances multiples
Le multitâche est au cœur du fenêtrage sur ordinateur. Autoriser plusieurs instances de votre application peut considérablement augmenter la productivité des utilisateurs.
Android 15 introduit PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI, que les applications peuvent définir pour spécifier que l'UI système doit être affichée pour que l'application puisse être lancée en tant qu'instances multiples.
Vous pouvez déclarer PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI dans le AndroidManifest.xml de votre application au sein du 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>
Gérer les instances d'application avec des gestes de déplacement
En mode multifenêtre, les utilisateurs peuvent démarrer une nouvelle instance d'application en faisant glisser un élément de vue hors de la fenêtre de l'application. Les utilisateurs peuvent également déplacer des éléments entre des instances de la même application.
Android 15 introduit deux indicateurs permettant de personnaliser le comportement de déplacement :
DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: indique qu'un déplacement non géré doit être délégué au système pour être démarré si aucune fenêtre visible ne gère le dépôt. Lorsque cet indicateur est utilisé, l'appelant doit fournirClipDataavec unClipData.Itemcontenant unIntentSenderimmuable pour une activité à lancer (voirClipData.Item.Builder#setIntentSender()). Le système peut lancer ou non l'intention en fonction de facteurs tels que la taille de l'écran ou le mode de fenêtrage actuels. Si le système ne lance pas l'intent, celui-ci est annulé à l'aide du flux de déplacement normal.DRAG_FLAG_GLOBAL_SAME_APPLICATION: indique qu'une opération de déplacement peut traverser les limites de la fenêtre (pour plusieurs instances de la même application).Lorsque [
startDragAndDrop()][20] est appelé avec ce flag défini, seules les fenêtres visibles appartenant à la même application peuvent participer à l'opération de déplacement et recevoir le contenu déplacé.
L'exemple suivant montre comment utiliser ces indicateurs avec 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
}
Optimisations supplémentaires
Personnalisez le lancement des applications et passez du mode fenêtrage du bureau au plein écran.
Spécifier la taille et la position par défaut
Toutes les applications, même redimensionnables, n'ont pas besoin d'une grande fenêtre pour offrir de la valeur aux utilisateurs.
Vous pouvez utiliser la méthode ActivityOptions#setLaunchBounds() pour spécifier une taille et une position par défaut lorsqu'une activité est lancée.
Voici un exemple de définition des limites de lancement pour une activité :
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())
Passer en mode plein écran depuis l'espace de bureau
Les applications peuvent passer en plein écran en appelant Activity#requestFullScreenMode().
La méthode affiche l'application en plein écran directement à partir du fenêtrage du bureau.
Pour demander le mode plein écran à partir d'une activité, utilisez le code suivant :
// In an Activity
fun enterFullScreen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { // Android 15 (U)
requestFullScreenMode()
}
}