Mit dem Desktop-Freiform-Fenster können Nutzer mehrere Apps gleichzeitig in App-Fenstern mit anpassbarer Größe ausführen und so ein vielseitiges, desktopähnliches Erlebnis genießen.
In Abbildung 1 sehen Sie die Organisation des Bildschirms mit aktiviertem Desktop-Freiform-Fenster. Hinweise:
- Nutzer können mehrere Apps gleichzeitig nebeneinander ausführen.
- Die Taskleiste befindet sich an einer festen Position unten auf dem Display und zeigt die ausgeführten Apps an. Nutzer können Apps für den schnellen Zugriff anpinnen.
- Eine neue anpassbare Kopfzeile ziert die Oberseite jedes Fensters mit Steuerelementen wie „Minimieren“ und „Maximieren“.
Standardmäßig werden Apps auf Android-Tablets im Vollbildmodus geöffnet. Wenn Sie eine App im Desktop-Freiform-Fenster starten möchten, halten Sie den Fenstergriff oben auf dem Bildschirm gedrückt und ziehen Sie ihn in der Benutzeroberfläche, wie in Abbildung 2 zu sehen.
Wenn eine App im Desktop-Freiform-Fenster geöffnet ist, werden auch andere Apps in Desktop-Fenstern geöffnet.
Nutzer können das Desktop-Freiform-Fenster auch über das Menü aufrufen, das unter dem Fenstergriff angezeigt wird, wenn Sie auf den Griff tippen oder klicken oder die Tastenkombination Meta-Taste (Windows, Befehlstaste oder Suche) + Strg + Nach unten verwenden.
Nutzer beenden das Desktop-Freiform-Fenster, indem sie alle aktiven Fenster schließen oder den Fenstergriff oben in einem Desktop-Fenster greifen und die App nach oben auf den Bildschirm ziehen. Mit der Tastenkombination Meta + H wird das Desktop Freiform-Fenster ebenfalls beendet und Apps werden wieder im Vollbildmodus ausgeführt.
Wenn Sie zum Desktop-Freiform-Fenster zurückkehren möchten, tippen oder klicken Sie auf die Kachel „Desktop-Bereich“ auf dem Bildschirm „Letzte“.
Größenänderung und Kompatibilitätsmodus
Im Desktop-Freiform-Fenster können Apps mit gesperrter Ausrichtung frei in der Größe angepasst werden. Das bedeutet, dass Nutzer die Größe der App auch dann in ein Fenster im Querformat ändern können, wenn eine Aktivität auf das Hochformat gesperrt ist.
Bei Apps, die als nicht größenveränderbar deklariert sind (resizeableActivity = false), wird
die Benutzeroberfläche skaliert, wobei das Seitenverhältnis beibehalten wird.
Bei Kamera-Apps, die die Ausrichtung sperren oder als nicht größenveränderbar deklariert sind, wird der Kamerasucher speziell behandelt: Die Größe des Fensters kann vollständig angepasst werden, aber das Seitenverhältnis des Suchers bleibt gleich. Wenn davon ausgegangen wird, dass Apps immer im Hoch- oder Querformat ausgeführt werden, werden die Apps fest codiert oder es werden Annahmen getroffen, die zu Fehlberechnungen der Ausrichtung oder des Seitenverhältnisses des Vorschaubilds oder des aufgenommenen Bilds führen. Das Ergebnis sind gestreckte, seitliche oder umgedrehte Bilder.
Bis Apps vollständig responsive Kamerasucher implementieren können, bietet die spezielle Behandlung eine einfachere Nutzererfahrung, die die Auswirkungen falscher Annahmen minimiert.
Weitere Informationen zum Kompatibilitätsmodus für Kamera-Apps finden Sie unter Geräte kompatibilitätsmodus.
Anpassbare Kopfzeileneinrückungen
Alle Apps, die im Desktop-Freiform-Fenster ausgeführt werden, haben eine Kopfzeile, auch im immersiven Modus. Sie können diese Leiste anpassen, um zu verhindern, dass der Inhalt Ihrer App verdeckt wird, und um benutzerdefinierte UI-Elemente direkt in den Kopfzeilenbereich einzufügen.
Implementierung
Wenn Sie benutzerdefinierte Inhalte in die Kopfzeile einfügen möchten, müssen Sie zuerst den Hintergrund der Kopfzeile transparent machen. Dazu können Sie das
APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND Flag mit dem
WindowInsetsController verwenden.
window.insetsController?.setSystemBarsAppearance( WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND, WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND )
Sobald die Kopfzeile transparent ist, können Sie den Kopfzeilenbereich an das Design Ihrer App anpassen. Verwenden Sie WindowInsets.isCaptionBarVisible, um zu erkennen, ob die Leiste
vorhanden ist, und wenden Sie die entsprechende Höhe oder den entsprechenden Abstand auf Ihr Layout an.
@OptIn(ExperimentalLayoutApi::class) @Composable fun CaptionBar() { if (WindowInsets.isCaptionBarVisible) { Row( modifier = Modifier .windowInsetsTopHeight(WindowInsets.captionBar) .fillMaxWidth() .background(if (isSystemInDarkTheme()) Color.White else Color.Black), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Caption Bar Title", style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(4.dp) ) } } }
setSystemBarsAppearance(appearance,mask): Konfiguriert den visuellen Stil der Systemleisten. Der erste Parameter definiert die Flags für das Ziel-Erscheinungsbild, während der zweite als Maske dient, um zu steuern, welche spezifischen Flags geändert werden.windowInsetsTopHeight(): Legt automatisch die Höhe Ihres Composables so fest, dass sie der Kopfzeile des Systems entspricht. So kann der benutzerdefinierte Hintergrund den Titelbereich ausfüllen, ohne Pixelwerte fest zu codieren.WindowInsets.captionBar: Gibt die Abmessungen für die Steuerelemente des Desktop Freiform-Fensters an (Schließen, Maximieren usw.). So kann die Größe der Benutzeroberfläche automatisch angepasst oder sie kann ausgeblendet werden, wenn Sie das Desktop-Freiform-Fenster aufrufen oder verlassen.
Weitere Informationen finden Sie unter Fenster-Insets. Neben einem Titel können Sie in der Kopfzeile auch andere UI-Elemente anzeigen, z. B. Tabs wie in Google Chrome, Suchleisten oder Profilavatare.
Benutzeroberfläche
Um zu verhindern, dass sich Ihre Benutzeroberfläche mit Systemschaltflächen überschneidet, bietet Android 15 die
WindowInsets#getBoundingRects() Methode. Die Methode gibt eine Liste von
Rect Objekten zurück, die Bereiche darstellen, die von Systemelementen belegt sind. Der verbleibende Platz in der Kopfzeile ist eine sichere Zone , in der Sie benutzerdefinierte Inhalte platzieren können.
Mit
APPEARANCE_LIGHT_CAPTION_BARS können Sie das Erscheinungsbild von System-Kopfzeilenelementen für helle und dunkle Designs umschalten. Greifen Sie in Compose mit
WindowInsets.Companion.captionBar() oder in Views mit
WindowInsets.Type.captionBar() auf Insets zu.
Weitere Informationen finden Sie unter Fenster-Insets.
Multitasking und Unterstützung für mehrere Instanzen
Multitasking ist das Herzstück des Desktop-Freiform-Fensters. Wenn Sie mehrere Instanzen Ihrer App zulassen, kann die Produktivität der Nutzer erheblich gesteigert werden.
Ab Android 15 können Sie
PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI verwenden. Wenn Sie diese Eigenschaft in Ihrer AndroidManifest.xml festlegen, geben Sie an, dass die System-UI Optionen (z. B. eine Schaltfläche „Neues Fenster“) bereitstellen soll, damit die App in mehreren Instanzen gestartet werden kann.
<application>
<property
android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
android:value="true" />
</application>
Hinweis:Im Desktop-Freiform-Fenster und in anderen Umgebungen mit mehreren Fenstern werden neue Aufgaben in einem neuen Fenster geöffnet. Überprüfen Sie daher den Nutzerpfad, wenn Ihre App mehrere Aufgaben startet.
App-Instanzen mit Ziehgesten verwalten
Im Modus mit mehreren Fenstern können Nutzer eine neue App-Instanz starten, indem sie ein UI-Element (z. B. einen Tab oder ein Dokument) aus dem Fenster der App ziehen. Nutzer können auch Elemente zwischen verschiedenen Instanzen derselben App verschieben.
Daten per Drag-and-drop übertragen
Wenn Sie ein Composables als Drag-Quelle für Drag-and-drop mit mehreren Instanzen konfigurieren möchten,
damit Nutzer Inhalte in eine andere Instanz Ihrer App ziehen oder eine
neue Instanz erstellen können, indem sie Inhalte in einen leeren Bereich des Bildschirms ziehen, verwenden Sie den
dragAndDropSource Modifikator. Geben Sie in der Lambda-Funktion
DragAndDropTransferData zurück und übergeben Sie die ClipData mit den zu
übertragenden Daten und Flags zur Konfiguration des Verhaltens bei mehreren Instanzen.
Android 15 führt zwei wichtige Flags für das Desktop-Freiform-Fenster und Interaktionen mit mehreren Instanzen ein:
DRAG_FLAG_GLOBAL_SAME_APPLICATION: Gibt an, dass ein Drag-Vorgang Fenstergrenzen überschreiten kann (für mehrere Instanzen derselben Anwendung). WennstartDragAndDrop()mit diesem Flag aufgerufen wird, können nur sichtbare Fenster derselben Anwendung am Drag-Vorgang teilnehmen und die gezogenen Inhalte empfangen.
Modifier.dragAndDropSource { _ -> DragAndDropTransferData( clipData = ClipData.newPlainText("label", "Your data"), flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION ) }
DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: Ermöglicht Nutzern, eine neue Instanz Ihrer App zu starten, indem sie die gezogenen Inhalte in einen leeren Bereich des Bildschirms ziehen, wenn kein anderes Fenster den Drop verarbeitet.- Wenn Sie dieses Flag verwenden, müssen Sie mit
ClipData.Item.Builder#setIntentSender()einenIntentSenderangeben, mit dem das System die neue Aktivität startet, wenn ein nicht verarbeiteter Drop auftritt.
- Wenn Sie dieses Flag verwenden, müssen Sie mit
Modifier.dragAndDropSource { _ -> val intent = Intent.makeMainActivity(activity.componentName).apply { putExtra("EXTRA_ITEM_ID", itemId) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT } val pendingIntent = PendingIntent.getActivity( activity, 0, intent, PendingIntent.FLAG_IMMUTABLE ) val data = ClipData( "Item $itemId", arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT), ClipData.Item.Builder().setIntentSender(pendingIntent.intentSender).build() ) DragAndDropTransferData( clipData = data, flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION or View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG, ) }
Übertragene Daten empfangen
Wenn Sie Daten von einer anderen Instanz akzeptieren möchten, verwenden Sie den dragAndDropTarget Modifikator.
Sie müssen Berechtigungen explizit anfordern, wenn die Daten von einer anderen Instanz oder App stammen.
Modifier.dragAndDropTarget( shouldStartDragAndDrop = { event -> event.toAndroidDragEvent().clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) }, target = object : DragAndDropTarget { override fun onDrop(event: DragAndDropEvent): Boolean { requestDragAndDropPermissions(activity, event.toAndroidDragEvent()) val clipData = event.toAndroidDragEvent().clipData val item = clipData?.getItemAt(0)?.text if (item != null) { // Process the dropped text item here } return item != null } } )
Wichtige Schritte :
- Filtern: Verwenden Sie
shouldStartDragAndDrop, um zu prüfen, ob die eingehenden Daten (MIME-Typ) unterstützt werden. - Berechtigungen: Rufen Sie
requestDragAndDropPermissions(event)auf, um auf die Daten zuzugreifen. - Verarbeiten: Extrahieren Sie die Daten im
onDrop-Callback.
Zusätzliche Optimierungen
Passen Sie App-Starts an und wechseln Sie von Apps im Desktop-Freiform-Fenster zum Vollbildmodus.
Standardgröße und -position angeben
Nicht alle Apps benötigen ein großes Fenster, um Nutzern einen Mehrwert zu bieten, auch wenn die Größe angepasst werden kann. Mit der
Methode ActivityOptions#setLaunchBounds() können Sie eine Standard
größe und -position festlegen, wenn eine Aktivität gestartet wird.
Vollbildmodus über den Desktop-Bereich aufrufen
Apps können mit Activity#requestFullScreenMode() in den Vollbildmodus wechseln. Die Methode zeigt die App direkt aus dem Desktop-Freiform-Fenster im Vollbildmodus an.