Unterstützung von dreifach faltbaren Geräten und faltbaren Geräten im Querformat

Ein faltbares Smartphone im Querformat in geschlossenem und vollständig geöffnetem Zustand neben einem faltbaren Smartphone mit drei Displays in geschlossenem und vollständig geöffnetem Zustand.

Entwickler stehen oft vor besonderen Herausforderungen, wenn sie Anwendungen für Foldables erstellen – insbesondere für Geräte wie das Samsung Trifold oder das ursprüngliche Pixel Fold, das im Querformat geöffnet wird (rotation_0 = landscape). Häufige Fehler von Entwicklern sind:

  • Falsche Annahmen zur Geräteausrichtung
  • Übersehene Anwendungsfälle
  • Werte werden bei Konfigurationsänderungen nicht neu berechnet oder im Cache gespeichert

Zu den gerätespezifischen Problemen gehören:

  • Eine Abweichung in der natürlichen Ausrichtung des Geräts zwischen dem Cover- und dem inneren Display (Annahmen basierend auf rotation_0 = portrait), wodurch Apps beim Auf- und Zuklappen nicht funktionieren
  • Unterschiedliche Bildschirmdichten und falsche Verarbeitung von density-Konfigurationsänderungen
  • Probleme mit der Kameravorschau, die durch die Abhängigkeit des Kamerasensors von der natürlichen Ausrichtung verursacht werden

Um auf Foldables eine hohe Nutzerfreundlichkeit zu bieten, sollten Sie sich auf die folgenden wichtigen Bereiche konzentrieren:

  • Bestimmen Sie die Ausrichtung der App anhand des tatsächlichen Bildschirmbereichs, den die App einnimmt, und nicht anhand der physischen Ausrichtung des Geräts.
  • Aktualisieren Sie die Kameravorschau, um die Geräteausrichtung und das Seitenverhältnis korrekt zu verwalten, seitliche Vorschauen zu vermeiden und zu verhindern, dass Bilder gestreckt oder zugeschnitten werden.
  • Sorgen Sie dafür, dass die App beim Auf- oder Zuklappen des Geräts weiterhin funktioniert. Behalten Sie dazu den Status mit ViewModel oder ähnlichen Ansätzen bei oder verarbeiten Sie Änderungen der Bildschirmdichte und Ausrichtung manuell. So vermeiden Sie App-Neustarts oder den Verlust des Status.
  • Passen Sie für Apps, die Bewegungssensoren verwenden, das Koordinatensystem an die aktuelle Ausrichtung des Bildschirms an und vermeiden Sie Annahmen basierend auf rotation_0 = portrait, um präzise Nutzerinteraktionen zu gewährleisten.

Adaptive Apps entwickeln

Wenn Ihre App bereits adaptiv ist und der optimierten Stufe (Stufe 2) entspricht, die in den Richtlinien zur adaptiven App-Qualität beschrieben ist, sollte die App auf Foldables gut funktionieren. Andernfalls sollten Sie, bevor Sie die spezifischen Details von Trifold- und Landscape-Foldables überprüfen, die folgenden grundlegenden Konzepte der adaptiven Android-Entwicklung kennen.

Adaptive Layouts

Ihre Benutzeroberfläche muss nicht nur mit unterschiedlichen Bildschirmgrößen, sondern auch mit Echtzeitänderungen des Seitenverhältnisses umgehen können, z. B. beim Aufklappen und beim Wechsel in den Multi-Window- oder Desktop-Freiform-Fenster-Modus. Weitere Informationen finden Sie unter Adaptive Layouts.

  • Adaptive Layouts entwerfen und implementieren
  • Primäre Navigation der App an die Fenstergröße anpassen
  • Fenstergrößenklassen verwenden, um die Benutzeroberfläche der App anzupassen
  • Implementierung kanonischer Layouts wie Liste/Details mit den Jetpack APIs vereinfachen
Eine App mit Letterboxing auf einem geöffneten faltbaren Gerät und dieselbe App im Vollbildmodus mit einem adaptiven Layout auf einem anderen geöffneten faltbaren Gerät.
Abbildung 1. Unterschied zwischen nicht adaptiven (Letterbox) und adaptiven Layouts.

Fenstergrößenklassen

Foldables, einschließlich Landscape-Foldables und Trifolds, können sofort zwischen den Fenstergrößenklassen „Kompakt“, „Mittel“ und „Erweitert“ wechseln. Wenn Sie diese Klassen kennen und implementieren, wird in Ihrer App die korrekte Navigation und Inhaltsdichte für den aktuellen Gerätestatus angezeigt.

Darstellung einer App auf Geräten mit den Fenstergrößenklassen „Kompakt“, „Mittel“ und „Erweitert“.
Abbildung 2. Fenstergrößenklassen.

Im folgenden Beispiel wird die adaptive Material 3-Bibliothek verwendet, um zu ermitteln, wie viel Platz die App zur Verfügung hat. Dazu wird zuerst die currentWindowAdaptiveInfo() Funktion aufgerufen und dann die entsprechenden Layouts für die drei Fenstergrößenklassen verwendet:

val adaptiveInfo = currentWindowAdaptiveInfo()
val windowSizeClass = adaptiveInfo.windowSizeClass

when {
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Expanded
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
  else -> // Compact
}

Weitere Informationen finden Sie unter Fenstergrößenklassen verwenden.

Adaptive App-Qualität

Wenn Sie die Stufe 2 (adaptiv optimiert) oder Stufe 1 (adaptiv differenziert) der Richtlinien zur adaptiven App-Qualität einhalten, bietet Ihre App eine überzeugende Nutzerfreundlichkeit auf Trifolds, Landscape-Foldables und anderen Geräten mit großen Displays. Die Richtlinien umfassen wichtige Prüfungen auf mehreren Stufen, um von einer adaptiven App zu einer differenzierten Nutzerfreundlichkeit zu gelangen.

Android 16 und höher

Bei Apps, die auf Android 16 (API-Level 36) und höher ausgerichtet sind, ignoriert das System Einschränkungen für Ausrichtung, Größenänderung und Seitenverhältnis auf Displays mit einer kleinsten Breite von mindestens 600 dp. Apps füllen das gesamte Anzeigefenster, unabhängig von Seitenverhältnis oder der bevorzugten Ausrichtung des Nutzers. Der Letterbox -Kompatibilitätsmodus wird nicht mehr verwendet.

Besonderheiten

Trifolds und Landscape-Foldables haben ein einzigartiges Hardwareverhalten, das eine spezielle Handhabung erfordert, insbesondere in Bezug auf Sensoren, Kameravorschau und Konfigurationskontinuität (Status beibehalten beim Auf-, Zuklappen oder Ändern der Größe).

Kameravorschau

Ein häufiges Problem bei Landscape-Foldables oder bei Berechnungen des Seitenverhältnisses (in Szenarien wie Multi-Window, Desktop-Freiform-Fenster-Modus oder angeschlossene Displays) ist, dass die Kameravorschau gestreckt, seitlich, zugeschnitten oder gedreht angezeigt wird.

Annahmen stimmen nicht überein

Dieses Problem tritt häufig auf Geräten mit großen Displays und Foldables auf, da Apps feste Beziehungen zwischen Kamerafunktionen (z. B. Seitenverhältnis und Sensorausrichtung) und Gerätefunktionen (z. B. Geräteausrichtung und natürliche Ausrichtung) annehmen können.

Neue Formfaktoren stellen diese Annahme infrage. Bei einem Foldable können sich die Displaygröße und das Seitenverhältnis ändern, ohne dass sich die Geräteausrichtung ändert. Wenn Sie beispielsweise ein Gerät aufklappen, ändert sich das Seitenverhältnis. Wenn der Nutzer das Gerät jedoch nicht dreht, bleibt die Ausrichtung gleich. Wenn eine App davon ausgeht, dass das Seitenverhältnis mit der Geräteausrichtung zusammenhängt, kann sie die Kameravorschau falsch drehen oder skalieren. Dasselbe kann passieren, wenn eine App davon ausgeht, dass die Ausrichtung des Kamerasensors mit der Ausrichtung des Geräts im Hochformat übereinstimmt. Das ist bei Landscape-Foldables nicht immer der Fall.

Lösung 1: Jetpack CameraX (empfohlen)

Die einfachste und robusteste Lösung ist die Verwendung der Jetpack CameraX-Bibliothek. Sein PreviewView UI-Element ist so konzipiert, dass es alle Komplexitäten der Vorschau automatisch verarbeitet:

  • PreviewView wird korrekt an die Sensorausrichtung, die Geräteausrichtung und die Skalierung angepasst.
  • Das Seitenverhältnis des Kamerabilds wird beibehalten, in der Regel durch Zentrieren und Zuschneiden (FILL_CENTER).
  • Sie können den Skalierungstyp auf FIT_CENTER festlegen, um die Vorschau bei Bedarf mit Letterboxing zu versehen.

Weitere Informationen finden Sie unter Vorschau in der CameraX-Dokumentation implementieren.

Lösung 2: CameraViewfinder

Wenn Sie eine vorhandene Camera2-Codebasis verwenden, ist die Bibliothek CameraViewfinder (abwärtskompatibel zu API-Level 21) eine weitere moderne Lösung. Sie vereinfacht die Anzeige des Kamerafeeds, indem sie ein TextureView oder SurfaceView verwendet und alle erforderlichen Transformationen (Seitenverhältnis, Skalierung und Drehung) für Sie anwendet.

Weitere Informationen finden Sie im Blogpost Introducing Camera Viewfinder und im Entwicklerleitfaden zur Kameravorschau.

Lösung 3: Manuelle Camera2-Implementierung

Wenn Sie CameraX oder CameraViewfinder nicht verwenden können, müssen Sie die Ausrichtung und das Seitenverhältnis manuell berechnen und dafür sorgen, dass die Berechnungen bei jeder Konfigurationsänderung aktualisiert werden:

  • Rufen Sie die Ausrichtung des Kamerasensors (z. B. 0, 90, 180, 270 Grad) aus CameraCharacteristics ab.
  • Rufen Sie die aktuelle Displayausrichtung des Geräts ab (z. B. 0, 90, 180, 270 Grad).
  • Verwenden Sie diese beiden Werte, um die erforderlichen Transformationen für Ihr SurfaceView oder TextureView zu bestimmen.
  • Achten Sie darauf, dass das Seitenverhältnis Ihres Ausgabetyps Surface mit dem Seitenverhältnis der Kameravorschau übereinstimmt, um Verzerrungen zu vermeiden.
  • Die Kamera-App wird möglicherweise in einem Teil des Bildschirms ausgeführt, entweder im Multi-Window- oder Desktop-Freiform-Fenster-Modus oder auf einem angeschlossenen Display. Daher sollte die Bildschirmgröße nicht verwendet werden, um die Abmessungen des Kamerasuchers zu bestimmen. Verwenden Sie stattdessen Fenstermesswerte.

Weitere Informationen finden Sie im Entwicklerleitfaden zur Kameravorschau und im Video Your Camera app on different form factors.

Lösung 4: Grundlegende Kameraaktionen mit einem Intent ausführen

Wenn Sie nicht viele Kamerafunktionen benötigen, ist es eine einfache Lösung, grundlegende Kameraaktionen wie das Aufnehmen eines Fotos oder Videos mit der Standardkamera-App des Geräts auszuführen. Sie müssen keine Kamera-Bibliothek einbinden, sondern verwenden stattdessen einen Intent.

Weitere Informationen finden Sie unter Kamera-Intents.

Konfiguration und Kontinuität

Foldables bieten mehr Vielseitigkeit bei der Benutzeroberfläche, können aber mehr Konfigurationsänderungen auslösen als nicht faltbare Geräte. Ihre App muss diese Konfigurationsänderungen und ihre Kombinationen verarbeiten, z. B. Geräteausrichtung, Auf-/Zuklappen und Größenänderung des Fensters im Multi-Window- oder Desktop-Modus, während der App-Status beibehalten oder wiederhergestellt wird. Apps müssen beispielsweise die folgende Kontinuität beibehalten:

  • App-Status ohne Abstürze oder störende Änderungen für Nutzer (z. B. beim Wechseln zwischen Bildschirmen oder beim Senden der App in den Hintergrund)
  • Scrollposition von scrollbaren Feldern
  • In Textfelder eingegebener Text und Tastaturstatus
  • Wiedergabeposition von Medien, damit die Wiedergabe an der Stelle fortgesetzt wird, an der sie beim Start der Konfigurationsänderung unterbrochen wurde

Zu den häufig ausgelösten Konfigurationsänderungen gehören screenSize, smallestScreenSize, screenLayout, orientation, density, fontScale, touchscreen und keyboard.

Weitere Informationen finden Sie unter android:configChanges und Konfigurationsänderungen verarbeiten. Weitere Informationen zum Verwalten des App-Status finden Sie unter UI-Status speichern.

Konfigurationsänderungen der Dichte

Die äußeren und inneren Displays von Trifolds und Landscape-Foldables können unterschiedliche Pixeldichten aufweisen. Daher erfordert die Verwaltung der Konfigurationsänderung für density besondere Aufmerksamkeit. Android startet die Aktivität in der Regel neu, wenn sich die Displaydichte ändert, was zu Datenverlust führen kann. Damit das System die Aktivität nicht neu startet, deklarieren Sie die Dichtebehandlung in Ihrem Manifest und verwalten Sie die Konfigurationsänderung programmatisch in Ihrer App.

AndroidManifest.xml-Konfiguration

  • density: Deklariert, dass die App die Änderung der Bildschirmdichte verarbeitet
  • Andere Konfigurationsänderungen: Es ist auch sinnvoll, andere häufig auftretende Konfigurationsänderungen zu deklarieren, z. B. screenSize, orientation, keyboardHidden, fontScale usw.

Durch das Deklarieren der Dichte (und anderer Konfigurationsänderungen) wird verhindert, dass das System die Aktivität neu startet. Stattdessen wird onConfigurationChanged() aufgerufen.

onConfigurationChanged()-Implementierung

Wenn sich die Dichte ändert, müssen Sie Ihre Ressourcen im Callback aktualisieren (z. B. Bitmaps neu laden oder Layoutgrößen neu berechnen):

  • Prüfen Sie, ob sich die DPI in newConfig.densityDpi geändert hat.
  • Setzen Sie benutzerdefinierte Ansichten, benutzerdefinierte Drawables usw. auf die neue Dichte zurück.

Zu verarbeitende Ressourcenelemente

  • Bildressource: Ersetzen Sie Bitmaps und Drawables durch dichteabhängige Ressourcen oder passen Sie die Skalierung direkt an.
  • Layout-Einheit (Konvertierung von dp in px): Berechnen Sie die Ansichtsgröße, den Rand und den Innenabstand neu.
  • Schriftart und Textgröße: Wenden Sie die Textgröße der Einheit „sp“ neu an.
  • Benutzerdefinierte View/Canvas Zeichnung: Aktualisieren Sie die pixelbasierten Werte, die zum Zeichnen von Canvas verwendet werden.

App-Ausrichtung bestimmen

Verlassen Sie sich beim Erstellen adaptiver Apps niemals auf die physische Geräteausrichtung, da sie auf Geräten mit großen Displays ignoriert wird und eine App im Multi-Window-Modus eine andere Ausrichtung als das Gerät haben kann. Verwenden Sie stattdessen Configuration.orientation oder WindowMetrics, um anhand der Fenstergröße zu ermitteln, ob Ihre App derzeit im Quer- oder Hochformat angezeigt wird.

Lösung 1: Configuration.orientation verwenden

Diese Property gibt die Ausrichtung an, in der Ihre App derzeit angezeigt wird.

Lösung 2: WindowMetrics#getBounds() verwenden

Sie können die aktuellen Anzeigegrenzen der App abrufen und ihre Breite und Höhe prüfen, um die Ausrichtung zu bestimmen.

Wenn Sie die App-Ausrichtung auf Smartphones (oder den äußeren Displays von Foldables) einschränken möchten, aber nicht auf Geräten mit großen Displays, lesen Sie App-Ausrichtung auf Smartphones einschränken.

Positionen und Anzeigemodi

Foldable-Positionen und ‑Status wie „Tischmodus“ und HALF_OPENED werden sowohl von Foldables im Hoch- als auch im Querformat unterstützt. Trifolds unterstützen jedoch keine Tischposition und können nicht im Modus HALF_OPENED verwendet werden. Stattdessen bieten Trifolds einen größeren Bildschirm für eine einzigartige Nutzerfreundlichkeit, wenn sie vollständig aufgeklappt sind.

Um Ihre App auf Foldables zu differenzieren, die HALF_OPENED unterstützen, verwenden Sie Jetpack WindowManager APIs wie FoldingFeature.

Weitere Informationen zu Foldable-Positionen, ‑Status und zur Unterstützung der Kameravorschau finden Sie in den folgenden Entwicklerleitfäden:

Foldables bieten einzigartige Betrachtungserlebnisse. Mit dem Modus für das hintere Display und dem Dual-Screen-Modus können Sie spezielle Anzeigefunktionen für Foldables entwickeln, z. B. eine Vorschau für Rückkamera-Selfies und gleichzeitige, aber unterschiedliche Anzeigen auf den inneren und äußeren Displays. Weitere Informationen:

Ausrichtung auf die natürliche Sensorausrichtung festlegen

Für sehr spezifische Anwendungsfälle – insbesondere für Apps, die den gesamten Bildschirm unabhängig vom gefalteten Zustand des Geräts einnehmen müssen – können Sie mit dem Flag nosensor die App auf die natürliche Ausrichtung des Geräts festlegen. Auf einem Pixel Fold ist die natürliche Ausrichtung des Geräts im gefalteten Zustand beispielsweise das Hochformat, während die natürliche Ausrichtung im aufgeklappten Zustand das Querformat ist. Wenn Sie das Flag nosensor hinzufügen, wird die App im Hochformat gesperrt, wenn sie auf dem äußeren Display ausgeführt wird, und im Querformat, wenn sie auf dem inneren Display ausgeführt wird.

<activity
  android:name=".MainActivity"
  android:screenOrientation="nosensor">

Spiele und XR-Sensor-Remapping

Für Spiele und XR-Apps werden Rohsensordaten (z. B. Gyroskop oder Beschleunigungsmesser) im gerätefesten Koordinatensystem bereitgestellt. Wenn der Nutzer das Gerät dreht, um ein Spiel im Querformat zu spielen, drehen sich die Sensorachsen nicht mit dem Bildschirm, was zu falschen Spielsteuerungen führt.

Prüfen Sie zur Behebung dieses Problems die aktuelle Display.getRotation() und ordnen Sie die Achsen entsprechend neu zu:

  • Drehung 0: x=x, y=y
  • Drehung 90: x=-y, y=x
  • Drehung 180: x=-x, y=-y
  • Drehung 270: x=y, y=-x

Verwenden Sie für Rotationsvektoren (die in Kompass- oder XR-Apps verwendet werden) SensorManager.remapCoordinateSystem(), um die Richtung des Kameraobjektivs oder die Oberseite des Bildschirms basierend auf der aktuellen Drehung den neuen Achsen zuzuordnen.

App-Kompatibilität

Anwendungen müssen die Richtlinien zur App-Qualität einhalten, um die Kompatibilität auf allen Formfaktoren und angeschlossenen Displays zu gewährleisten. Wenn eine Anwendung die Richtlinien nicht einhalten kann, können Gerätehersteller Kompatibilitätsbehandlungen implementieren. Dies kann jedoch die Nutzerfreundlichkeit beeinträchtigen.

Weitere Informationen finden Sie in der umfassenden Liste der Kompatibilitäts Workarounds auf der Plattform, insbesondere zu Kameravorschau, Überschreibungen und Android 16 API-Änderungen, die das Verhalten Ihrer App ändern könnten.

Weitere Informationen zum Erstellen adaptiver Apps finden Sie in den Richtlinien zur adaptiven App-Qualität guidelines.