Foldables: Adaptive UIs für faltbare Displays entwickeln
Optimiere deine App für faltbare Displays. Lerne den Umgang mit Hinge, Posture und App Continuity für eine fließende User Experience auf jedem Gerät.
Faltbare Smartphones haben die Art und Weise, wie Nutzer mit ihren mobilen Geräten interagieren, maßgeblich verändert. Für dich als Android-Entwickler bedeutet diese Entwicklung, dass du dich nicht mehr auf feste Bildschirmgrößen, vordefinierte Seitenverhältnisse oder statische Layouts verlassen kannst. Die Anzeigeoberfläche kann sich im laufenden Betrieb verändern, aufgeteilt werden oder durch ein mechanisches Scharnier physisch unterbrochen sein. Diese unerwartete und ständige Dynamik erfordert ein völlig neues mentales Modell für die Konzeption und Programmierung von Benutzeroberflächen. Die zentrale Herausforderung besteht darin, Anwendungen so zu gestalten, dass sie sich elegant und verzögerungsfrei an diese physischen Veränderungen anpassen, ohne den Arbeitsfluss des Nutzers in irgendeiner Weise zu stören. Du musst dich intensiv mit neuen Konzepten wie der physikalischen Beschaffenheit des Scharniers, den unterschiedlichen Faltzuständen der Hardware und der nahtlosen Fortführung der App-Aktivität auseinandersetzen, um eine professionelle und qualitativ hochwertige Benutzererfahrung zu gewährleisten. Nur wenn du diese Prinzipien verinnerlichst, wird deine Applikation auf modernen Geräten wirklich glänzen und den Nutzern einen spürbaren Mehrwert gegenüber traditionellen Smartphones bieten.
Was ist das?
Foldables sind mobile Endgeräte, deren Bildschirme physisch gefaltet werden können. Im Android-Ökosystem stellen sie eine der wichtigsten Hardware-Entwicklungen der letzten Jahre dar. Im Gegensatz zu traditionellen Smartphones, die eine feste und unveränderliche Glasfläche bieten, variieren Foldables ihre Form und Größe je nachdem, wie der Nutzer sie hält und aufklappt. Aus der Perspektive der Softwareentwicklung sind Foldables keine völlig neuen Betriebssystemumgebungen, sondern eine Weiterentwicklung der bestehenden Android-Architektur für Multi-Window-Unterstützung und dynamische Konfigurationsänderungen.
Wenn du für Foldables entwickelst, musst du drei zentrale Konzepte verstehen: Hinge, Posture und Continuity. Das „Hinge“ ist das mechanische Scharnier, das den Bildschirm teilt oder stützt. Dieses Scharnier ist nicht nur ein physisches Bauteil, sondern eine sichtbare und spürbare Grenze im Displaybereich. Es kann einen toten Winkel erzeugen oder den Bildschirm in zwei logische Bereiche unterteilen. Unter „Posture“ versteht man den aktuellen Haltungszustand des Geräts. Ein Foldable kann flach auf dem Tisch liegen, wie ein Buch teilweise geöffnet sein oder im Zelt-Modus aufgestellt werden. Jeder dieser Zustände erfordert eine andere Darstellung deiner Applikation. „Continuity“ bezeichnet die Fähigkeit deiner App, den aktuellen Zustand beizubehalten, wenn sich die physische Form des Geräts ändert. Wenn ein Nutzer auf dem kleinen Außenbildschirm einen Text tippt und das Gerät aufklappt, muss der Cursor exakt an derselben Stelle im großen Innenbildschirm weiterblinken.
Die Entwicklung für faltbare Displays zwingt dich dazu, reaktive und anpassungsfähige Benutzeroberflächen zu konzipieren. Mit der Einführung von Jetpack Compose und modernen Architekturkomponenten stellt Google die Werkzeuge bereit, um diese Flexibilität deklarativ abzubilden. Du programmierst keine starren XML-Layouts mehr für eine bestimmte Auflösung, sondern beschreibst Zustände, die auf Veränderungen im verfügbaren Platz reagieren. Dies ist eine architektonische Notwendigkeit. Wenn du dich weigerst, diesen dynamischen Ansatz zu adaptieren, riskierst du, dass deine Anwendung auf Geräten der neuesten Generation fehlerhaft, unvollständig oder im schlimmsten Fall unbrauchbar erscheint. Die Nutzer erwarten, dass die Software die Hardware optimal ausnutzt. Jeder Moment, in dem eine App beim Falten ruckelt oder ihren Status verliert, ist ein Moment der Frustration, den es als professioneller Entwickler strikt zu vermeiden gilt.
Zusätzlich zur bloßen Darstellung von Inhalten verändert sich auch die ergonomische Erwartungshaltung. Nutzer halten ein halb geöffnetes Gerät anders als ein vollständig geöffnetes Tablet oder ein geschlossenes Smartphone. Deine Software muss diese physische Realität widerspiegeln. Ein Button, der auf einem flachen Bildschirm gut erreichbar ist, liegt bei einem teilweise gefalteten Gerät möglicherweise in einem Bereich, der für die Finger schwer zugänglich ist. Dieses Bewusstsein für die Hardware-Geometrie und die Ergonomie unterscheidet eine durchschnittliche App von einer herausragenden Anwendung.
Wie funktioniert es?
Die technische Umsetzung für Foldables basiert auf den WindowManager-APIs und dem Lifecycle-System von Android. Das Betriebssystem behandelt das Auf- oder Zuklappen eines Geräts als Konfigurationsänderung. Wenn sich die Posture ändert, wird die Activity standardmäßig neu erstellt, es sei denn, du fängst diese Änderung explizit ab. Um eine nahtlose Continuity zu gewährleisten, musst du den Zustand deiner Benutzeroberfläche sorgfältig speichern und wiederherstellen. Hierbei spielen ViewModels und savedInstanceState eine entscheidende Rolle. Der Lifecycle einer Activity auf einem Foldable kann extrem volatil sein. Während ein Nutzer das Gerät langsam öffnet, können im Hintergrund mehrfache Größenanpassungen getriggert werden. Deine Architektur muss robust genug sein, um diese schnellen Übergänge zu verkraften, ohne dabei teure Netzwerkanfragen neu zu starten oder Datenbankabfragen unnötig zu wiederholen. Eine saubere Trennung von Geschäftslogik und Darstellungslogik ist hierbei dein bester Schutz gegen unvorhersehbares Verhalten.
Der Jetpack WindowManager ist die zentrale Schnittstelle, um Informationen über die physischen Eigenschaften des Bildschirms zu erhalten. Er liefert dir Daten über sogenannte „Folding Features“. Ein solches Feature repräsentiert das Hinge und enthält Informationen über dessen Position, seine Ausrichtung und den Zustand. Das Hinge kann horizontal oder vertikal verlaufen, und der Zustand kann „Flat“ (flach) oder „Half Opened“ (halb geöffnet, auch Tabletop- oder Book-Modus genannt) sein. Diese Informationen erhältst du asynchron, was bedeutet, dass sich deine UI initial aufteilen und dann kurz darauf neu anordnen muss, sobald die Daten des WindowManagers vorliegen. Dieser asynchrone Fluss verlangt nach reaktiven Datenströmen.
Um die Posture effektiv zu verwalten, lauschst du auf Änderungen im Fenster-Layout. In Jetpack Compose nutzt du dafür Funktionen wie calculateWindowSizeClass, um die App in vordefinierte Größenkategorien (Compact, Medium, Expanded) einzuteilen. Dies reicht für einfache Anpassungen oft aus. Für tiefergehende Foldable-Unterstützung musst du jedoch den Flow von WindowInfoTracker abonnieren. Dieser Flow liefert eine Liste von DisplayFeature-Objekten. Sobald du ein Hinge identifizierst, kannst du dessen Koordinaten nutzen, um deine UI-Komponenten geschickt um diese physische Unterbrechung herum zu positionieren. Du musst die Bounds, also die genauen Pixelgrenzen des Scharniers auslesen, und diese als Margins oder Spacer in dein Layout integrieren, um zu verhindern, dass wichtiger Text von der Falz verschluckt wird.
Das Verständnis für die zugrundeliegenden Datenstrukturen ist essenziell. Die WindowMetrics liefern dir die absoluten Dimensionen des aktuellen Fensters. Doch erst in Kombination mit den DisplayFeature-Objekten ergibt sich ein vollständiges Bild. Wenn du den WindowInfoTracker verwendest, erhältst du bei jedem Faltvorgang ein neues Layout-Info-Objekt. Dieses enthält eine Liste von Features, die du iterieren musst. Du filterst dabei nach Instanzen vom Typ FoldingFeature. Sobald du ein solches Element isoliert hast, greifst du auf Eigenschaften wie orientation und state zu. Basierend auf diesen Werten triffst du in deiner UI-Schicht die Entscheidung, ob du zwei separate Ansichten anzeigst, die exakt an den Rändern des Hinge enden, oder ob du eine große, zusammenhängende Ansicht präsentierst. Ein klassisches Beispiel ist der Tabletop-Modus. Wenn das Gerät halb zugeklappt auf dem Tisch liegt, kannst du die obere Bildschirmhälfte für die Anzeige von Inhalten nutzen und die untere Hälfte für Steuerelemente. Die Mechanik dahinter erfordert, dass dein Layout auf die exakten Grenzen des Scharniers reagiert und keine interaktiven Elemente in dem Bereich platziert, der durch das Hinge schwer erreichbar oder optisch verzerrt ist.
In der Praxis
In deinem Entwickleralltag wirst du schnell feststellen, dass Foldables dein Verständnis von reaktivem Design intensiv auf die Probe stellen. Eine häufige Stolperfalle ist die Annahme, dass der gesamte sichtbare Bereich auch uneingeschränkt nutzbar ist. Wenn du ein Video über den gesamten Bildschirm spannst und der Nutzer das Gerät halb zusammenklappt, verläuft das Hinge mitten durch das Bild, was die Sichtbarkeit drastisch einschränkt. Ein weiterer kritischer Fehler ist die feste Verdrahtung von Bildschirmausrichtungen. Wenn du in deinem Manifest screenOrientation="portrait" festlegst, blockierst du auf vielen Foldables die korrekte Anpassung beim Aufklappen und zerstörst die gesamte User Experience. Deine App sollte immer flexibel auf Orientierungsänderungen reagieren.
Ein konkreter Anwendungsfall ist die Implementierung eines adaptiven Layouts mit Jetpack Compose. Angenommen, du hast eine App mit einer Liste von E-Mails und einer Detailansicht. Auf einem normalen Smartphone zeigst du entweder die Liste oder die Details. Auf einem aufgeklappten Foldable möchtest du beides nebeneinander anzeigen. Wenn das Foldable jedoch halb zugeklappt ist (Book-Modus), musst du sicherstellen, dass das Scharnier genau als visuelle Trennlinie zwischen der Liste und der Detailansicht dient.
Hier ist ein Konzept, wie du die Fenstergröße in Compose beurteilst, um Entscheidungen für das Layout zu treffen:
@Composable
fun AdaptiveEmailApp(windowSizeClass: WindowSizeClass) {
val isExpanded = windowSizeClass.widthSizeClass == WindowWidthSizeClass.Expanded
if (isExpanded) {
Row(modifier = Modifier.fillMaxSize()) {
EmailList(modifier = Modifier.weight(1f))
VerticalDivider()
EmailDetail(modifier = Modifier.weight(2f))
}
} else {
EmailList(modifier = Modifier.fillMaxSize())
}
}
Um jedoch auf das physische Hinge zu reagieren, benötigst du detailliertere Informationen. Du musst prüfen, ob ein FoldingFeature vorhanden ist und ob dessen Zustand HALF_OPENED entspricht. Eine typische Fehlerquelle ist es, die App Continuity zu ignorieren. Wenn der Nutzer das Gerät schließt, wechselt die App vom großen auf den kleinen Frontbildschirm. Viele Anwendungen verlieren dabei ihren Zustand, springen an den Anfang einer Liste zurück oder schließen offene Dialoge. Du vermeidest dies, indem du den Zustand deiner UI konsequent in einem ViewModel hältst und dich darauf verlässt, dass Compose die UI basierend auf diesem Zustand und den neuen Bildschirmmaßen neu zeichnet. Es ist unabdingbar, dass der Übergang zwischen den Displays absolut fließend stattfindet.
Darüber hinaus musst du das Testen dieser Zustände in deinen regulären Workflow integrieren. Du benötigst nicht zwingend teure Hardware, um mit der Entwicklung zu beginnen. Android Studio bietet hervorragende Emulatoren, die spezifische faltbare Geräte simulieren. In diesen Emulatoren kannst du Parameter wie den Winkel des Scharniers manuell über ein Kontrollfeld verändern. So überprüfst du direkt, ob sich deine Layouts fließend anpassen und ob die Continuity gewahrt bleibt. Schreibe zudem automatisierte UI-Tests, die diese Konfigurationsänderungen simulieren, um Regressionen zu vermeiden. Achte zudem darauf, dass Menüs, modale Dialoge und Tooltips nicht genau auf der Falte positioniert werden. Nutze die vom WindowManager bereitgestellten Insets und DisplayFeatures, um sicherzustellen, dass deine interaktiven Schaltflächen immer auf einer flachen, gut erreichbaren Seite des Bildschirms liegen.
Fazit
Foldables fordern ein tiefes Verständnis für reaktive Layouts und einen sauberen Umgang mit dem Lebenszyklus von Android-Komponenten. Du musst lernen, Hinge-Eigenschaften und Posture-Zustände aktiv abzufragen, um deine Applikation logisch im Raum zu strukturieren, während App Continuity sicherstellt, dass der Nutzerfluss niemals abbricht. Prüfe deine Layouts regelmäßig, indem du den Foldable-Emulator in Android Studio verwendest, simulierte Faltvorgänge während des Debuggings auslöst und gezielte UI-Tests schreibst, die Konfigurationsänderungen provozieren, um verlässlich zu verifizieren, dass kein Datenverlust auftritt.