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 erhalten.
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 den oberen Rand 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 Fensterziehpunkt 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 Fensterziehpunkt angezeigt wird, wenn Sie auf den Ziehpunkt 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 Fensterziehpunkt oben in einem Desktop-Fenster greifen und die App nach oben auf den Bildschirm ziehen. Mit der Meta + H Tastenkombination 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 „Zuletzt verwendet“.
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 Querformatfenster ändern können, wenn eine Aktivität auf das Hochformat gesperrt ist.
Bei Apps, die als nicht größenveränderbar deklariert sind (d. h.
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 der Sucher behält das gleiche Seitenverhältnis bei. Wenn davon ausgegangen wird, dass Apps immer im Hoch- oder Querformat ausgeführt werden, werden in den Apps Annahmen oder Festlegungen getroffen, die zu Fehlberechnungen der Ausrichtung oder des Seitenverhältnisses der Vorschau oder des aufgenommenen Bildes führen. Das Ergebnis sind verzerrte, seitliche oder auf dem Kopf stehende Bilder.
Bis Apps vollständig responsive Kamerasucher implementieren können, bietet die spezielle Behandlung eine einfachere Nutzererfahrung, die die Auswirkungen falscher Annahmen abmildert.
Weitere Informationen zum Kompatibilitätsmodus für Kamera-Apps finden Sie unter Gerätekompatibilitätsmodus.
Anpassbare Kopfzeileneinsätze
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 Inhalte Ihrer App verdeckt werden, 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 (z. B. Schließen und Maximieren ). So kann die Größe der Benutzeroberfläche automatisch angepasst oder sie 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 Titelleiste auch andere UI-Elemente anzeigen, z. B. Tabs wie in Google Chrome, Suchleisten oder Profilavatare.
Benutzeroberfläche
Um zu vermeiden, 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 Titelleiste ist eine sichere Zone , in der Sie benutzerdefinierte Inhalte platzieren können.
Mit
APPEARANCE_LIGHT_CAPTION_BARS können Sie das Erscheinungsbild von Systemelementen in der Titelleiste 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 Nutzerablauf immer, wenn Ihre App mehrere Aufgaben startet.
App-Instanzen mit Ziehgesten verwalten
Im Mehrfenstermodus 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 Composable 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 Modifikator dragAndDropSource. Geben Sie in der Lambda-Funktion DragAndDropTransferData zurück und übergeben Sie ClipData mit den zu übertragenden Daten und Flags zur Konfiguration des Verhaltens bei mehreren Instanzen.
In Android 15 werden zwei wichtige Flags für das Desktop-Freiform-Fenster und Interaktionen mit mehreren Instanzen eingeführt:
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 Desktop-Freiform-Fenstern 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 ActivityOptions#setLaunchBounds()
Methode können Sie eine Standardgröß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.