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, wie der Bildschirm aussieht, wenn das Desktop-Freiform-Fenster aktiviert ist. 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 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 Aktivitäten“.
App-Layout für eine desktopähnliche Umgebung optimieren
Das Design für einen Desktop kann sich erheblich vom mobilen Design unterscheiden, da mehr Bildschirmfläche zur Verfügung steht, die Eingabe über Maus und Tastatur präziser ist und eine hohe Produktivität erwartet wird.
Jetpack WindowManager bietet eine API, mit der Entwickler entscheiden können, wann eine Desktop-Benutzeroberfläche angezeigt werden soll. Diese hat in der Regel eine höhere Informationsdichte, andere Navigationsmuster und optimierte Mausinteraktionen.
lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { windowInfoTracker.windowEngagementInfo(this@DesktopWindowingActivity) .collect { windowEngagementInfo -> if(windowEngagementInfo.hasEngagementMode(WindowEngagementInfo.EngagementMode.PRECISE_POINTER)){ showDesktopOptimizedUI() }else { showTouchOptimizedUI() } } } }
Weitere Informationen finden Sie unter Design für Desktop.
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 an ein Fenster im Querformat anpassen 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 Sucher anders 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 in den Apps Annahmen getroffen, die zu Fehlberechnungen der Ausrichtung oder des Seitenverhältnisses der Vorschau oder des aufgenommenen Bildes führen. Dadurch können Bilder verzerrt, seitlich oder auf dem Kopf dargestellt werden.
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ä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, damit der Inhalt Ihrer App nicht verdeckt wird und benutzerdefinierte UI-Elemente direkt in den Kopfzeilenbereich eingefügt werden können.
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 die Höhe Ihres Composables automatisch 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 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 ein sicherer Bereich , in dem Sie benutzerdefinierte Inhalte platzieren können.
Mit
APPEARANCE_LIGHT_CAPTION_BARS können Sie das Erscheinungsbild von System-Titelleistenelementen 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 den Multi-Instanz-Modus
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-Benutzeroberfläche 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, 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 eine komponierbare Funktion als Ziehquelle für Drag-and-drop im Multi-Instanz-Modus 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 das ClipData, das die zu
übertragenden Daten enthält, sowie Flags zur Konfiguration des Multi-Instanz-Modus-Verhaltens.
Android 15 führt zwei wichtige Flags für das Desktop-Fenster und Interaktionen im Multi-Instanz-Modus ein:
DRAG_FLAG_GLOBAL_SAME_APPLICATION: Gibt an, dass ein Ziehvorgang Fenstergrenzen überschreiten kann (für mehrere Instanzen derselben Anwendung). WennstartDragAndDrop()mit diesem Flag aufgerufen wird, können nur sichtbare Fenster, die zur selben Anwendung gehören, an dem Ziehvorgang 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
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.