App faltbar erkennen

Große, aufgeklappte Displays und einzigartige zugeklappte Zustände ermöglichen neue Nutzererlebnisse auf faltbaren Geräten. Wenn deine App in Jetpack Compose auf das Falten reagieren soll, verwende die Compose Material 3 Adaptive-Bibliothek. Sie bietet APIs für Fensterfunktionen faltbarer Geräte wie Falten, Scharniere und Gerätepositionen. Wenn deine App auf das Falten reagiert, kann sie ihr Layout so anpassen, dass wichtige Inhalte nicht im Bereich von Falten oder Scharnieren platziert werden. Falten und Scharniere können als natürliche Trennlinien verwendet werden.

Wenn du weißt, ob ein Gerät Konfigurationen wie die Tisch- oder Buchposition unterstützt, kannst du besser entscheiden, ob du verschiedene Layouts unterstützen oder bestimmte Funktionen anbieten möchtest.

Fensterinformationen

Verwende in Jetpack Compose die collectFoldingFeaturesAsState() zusammensetzbare Funktion, um Informationen zum Falten des Fensters zu beobachten. collectFoldingFeaturesAsState() erfasst die aktuellen Fensterfunktionen von WindowInfoTracker in einem Compose-State, der eine Liste von FoldingFeature-Objekten enthält.

Da collectFoldingFeaturesAsState() einen Compose-State zurückgibt, werden deine zusammensetzbaren Funktionen automatisch neu zusammengesetzt, wenn sich der Faltzustand oder die Position des Geräts ändert. Eine manuelle Lebenszyklusverwaltung oder Flow-Erfassung ist nicht erforderlich:

@Composable
fun FoldAwareScreen() {
    val foldingFeatures by collectFoldingFeaturesAsState()

    // Access folding features for the current window.
    val foldFeature = foldingFeatures.firstOrNull()
    if (foldFeature != null) {
        // Adapt layout based on the fold feature.
    }
}

Funktionen faltbarer Displays

Die Liste der FoldingFeature-Elemente, die von collectFoldingFeaturesAsState() zurückgegeben werden (ein Untertyp von DisplayFeature) enthält Informationen zu faltbaren Displays, einschließlich der folgenden Attribute:

  • state: Der zugeklappte Zustand des Geräts, FLAT oder HALF_OPENED

  • orientation: Die Ausrichtung der Falte oder des Scharniers, HORIZONTAL oder VERTICAL

  • occlusionType: Gibt an, ob die Falte oder das Scharnier einen Teil des Displays verdeckt, NONE oder FULL

  • isSeparating: Gibt an, ob die Falte oder das Scharnier zwei logische Anzeigebereiche erstellt, „true“ oder „false“

Bei einem faltbaren Gerät, das HALF_OPENED ist, wird isSeparating immer als „true“ gemeldet, da der Bildschirm in zwei Anzeigebereiche unterteilt ist. Außerdem ist isSeparating auf einem Gerät mit zwei Bildschirmen immer „true“, wenn die Anwendung beide Bildschirme umfasst.

Das Attribut FoldingFeature bounds (geerbt von DisplayFeature) stellt das umgebende Rechteck einer Faltfunktion wie einer Falte oder eines Scharniers dar. Mit den Grenzen können Elemente auf dem Bildschirm relativ zur Funktion positioniert werden:

@Composable
fun FoldFeatureDemo() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    if (foldFeature != null) {
        val isSeparating = foldFeature.isSeparating
        val occlusionType = foldFeature.occlusionType
        val bounds = foldFeature.bounds
        // Use bounds and properties to position content.
    }
}

Tischposition

Mithilfe der Informationen im FoldingFeature-Objekt kann deine App Positionen wie die Tischposition unterstützen. Dabei liegt das Smartphone auf einer Oberfläche, das Scharnier befindet sich in horizontaler Position und der faltbare Bildschirm ist halb geöffnet.

Die Tischposition bietet Nutzern den Komfort, ihr Smartphone zu bedienen, ohne es in der Hand halten zu müssen. Die Tischposition eignet sich hervorragend zum Ansehen von Medien, Aufnehmen von Fotos und für Videoanrufe.

Eine Videoplayer-App im Modus „Auf dem Tisch“ mit Videowiedergabe im aufrechten vertikalen Teil des Bildschirms und Wiedergabesteuerelementen im unteren horizontalen Teil.
Abbildung 1 Eine Videoplayer-App in Tischposition: Video auf dem vertikalen Teil des Bildschirms, Wiedergabesteuerung auf dem horizontalen Teil.

Verwende FoldingFeature.State und FoldingFeature.Orientation aus collectFoldingFeaturesAsState(), um zu ermitteln, ob sich das Gerät in Tischposition befindet:

@Composable
fun TabletopContent() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    val isTableTopPosture = foldFeature != null &&
        foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL

    if (isTableTopPosture) {
        // Tabletop layout: separate content and controls across the fold.
    } else {
        // Standard layout.
    }
}

Alternativ kannst du prüfen, ob sich das Fenster in Tischposition befindet, indem du das Posture Attribut überprüfst, das von currentWindowAdaptiveInfoV2() zurückgegeben wird:

val adaptiveInfo = currentWindowAdaptiveInfoV2()
val isTabletop = adaptiveInfo.windowPosture.isTabletop

Sobald du weißt, dass sich das Gerät in Tischposition befindet, aktualisiere das Layout deiner App entsprechend. Bei Media-Apps bedeutet das in der Regel, dass die Wiedergabe oberhalb der Falte platziert wird und die Steuerelemente und zusätzlichen Inhalte direkt darunter positioniert werden, um eine freihändige Wiedergabe zu ermöglichen.

Beispiele

Buchposition

Eine weitere einzigartige Funktion faltbarer Geräte ist die Buchposition. Dabei ist das Gerät halb geöffnet und das Scharnier befindet sich in vertikaler Position. Die Buchposition eignet sich hervorragend zum Lesen von E‑Books. Mit einem zweiseitigen Layout auf einem großen faltbaren Bildschirm, der wie ein gebundenes Buch geöffnet ist, vermittelt die Buchposition das Gefühl, ein echtes Buch zu lesen.

Sie kann auch für die Fotografie verwendet werden, wenn du beim freihändigen Fotografieren ein anderes Seitenverhältnis aufnehmen möchtest.

Implementiere die Buchposition mit denselben Techniken wie die Tischposition. Prüfe, ob die Ausrichtung der Faltfunktion vertikal statt horizontal ist:

@Composable
fun BookContent() {
    val foldingFeatures by collectFoldingFeaturesAsState()
    val foldFeature = foldingFeatures.firstOrNull()

    val isBookPosture = foldFeature != null &&
        foldFeature.state == FoldingFeature.State.HALF_OPENED &&
        foldFeature.orientation == FoldingFeature.Orientation.VERTICAL

    if (isBookPosture) {
        // Book posture layout: two-page layout across the vertical fold.
    } else {
        // Standard single-page layout.
    }
}

Änderungen der Fenstergröße

Der Anzeigebereich einer App kann sich aufgrund einer Änderung der Gerätekonfiguration ändern, z. B. wenn das Gerät gefaltet oder aufgeklappt, gedreht oder im Mehrfenstermodus die Größe geändert wird.

Verwende in Jetpack Compose die currentWindowAdaptiveInfoV2() zusammensetzbare Funktion aus der Compose Material 3 Adaptive-Bibliothek, um die aktuelle Fenstergrößenklasse abzurufen und an Größenänderungen anzupassen. currentWindowAdaptiveInfoV2() gibt eine WindowAdaptiveInfo-Instanz zurück, die die WindowSizeClass des aktuellen Fensters (mit Unterstützung für große und besonders große Breakpoints standardmäßig) sowie die windowPosture des Geräts enthält:

@Composable
fun AdaptiveApp() {
    val adaptiveInfo = currentWindowAdaptiveInfoV2()
    val windowSizeClass = adaptiveInfo.windowSizeClass

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

Weitere Informationen findest du unter Fenstergrößenklassen verwenden.

Zusätzliche Ressourcen

Weitere Informationen zu Layouts, die auf das Falten reagieren, und zu faltbaren Geräten findest du in den folgenden Ressourcen:

Beispiele

  • Jetpack WindowManager-Beispiel: Beispiel für die Verwendung der Jetpack WindowManager-Bibliothek
  • Jetcaster : Implementierung der Tischposition mit Compose

Codelabs