Fenstereinsätze einrichten

Sobald deine Aktivität die Verarbeitung aller Insets übernommen hat, kannst du mit Compose-APIs prüfen, ob Inhalte verdeckt werden und ob interaktive Elemente sich mit der System-UI überschneiden. Diese APIs synchronisieren auch das Layout Ihrer App mit Änderungen an den Insets.

Einzüge mit Padding- oder Größenmodifikatoren verarbeiten

Dies ist beispielsweise die einfachste Methode, die Insets auf den Inhalt Ihrer gesamten App anzuwenden:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

In diesem Snippet werden die safeDrawing-Fenstereinsetzungen als Padding um den gesamten Inhalt der App angewendet. Dadurch wird zwar sichergestellt, dass interaktive Elemente sich nicht mit der System-UI überschneiden, aber auch, dass kein Teil der App hinter der System-UI gerendert wird, um einen Edge-to-Edge-Effekt zu erzielen. Damit das gesamte Fenster genutzt werden kann, müssen Sie die Insets für jeden Bildschirm oder jede Komponente einzeln anpassen.

Alle diese Inset-Typen werden automatisch mit IME-Animationen animiert, die auf API 21 zurückportiert wurden. Daher werden auch alle Ihre Layouts, die diese Insets verwenden, automatisch animiert, wenn sich die Inset-Werte ändern.

Es gibt drei Möglichkeiten, Insets zu verarbeiten, um Ihre zusammensetzbaren Layouts anzupassen:

Abstandsmodifikatoren

Modifier.windowInsetsPadding(windowInsets: WindowInsets) wendet die angegebenen Fenstereinsätze als Padding an, genau wie Modifier.padding. Mit Modifier.windowInsetsPadding(WindowInsets.safeDrawing) werden beispielsweise die Insets für den sicheren Zeichenbereich als Padding auf alle vier Seiten angewendet.

Außerdem gibt es mehrere integrierte Dienstprogrammmethoden für die gängigsten Inset-Typen. Modifier.safeDrawingPadding() ist eine solche Methode, die Modifier.windowInsetsPadding(WindowInsets.safeDrawing) entspricht. Für die anderen Inset-Typen gibt es analoge Modifikatoren.

Größenmodifikatoren für Insets

Die folgenden Modifikatoren wenden einen Betrag von Fenstereinsätzen an, indem sie die Größe der Komponente auf die Größe der Einsätze festlegen:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

Wendet die Startseite von „windowInsets“ als Breite an (wie Modifier.width).

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

Wendet die Endseite von „windowInsets“ als Breite an (z. B. Modifier.width).

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

Wendet die Oberseite von „windowInsets“ als Höhe an (wie Modifier.height).

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

Wendet die Unterseite von „windowInsets“ als Höhe an (z. B. Modifier.height).

Diese Modifizierer sind besonders nützlich, um die Größe eines Spacer festzulegen, das den Platz von Insets einnimmt:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Verbrauch von Insets

Die Inset-Padding-Modifikatoren (windowInsetsPadding und Helfer wie safeDrawingPadding) verwenden automatisch den Teil der Insets, der als Padding angewendet wird. Wenn Sie tiefer in den Kompositionsbaum gehen, wissen die verschachtelten Inset-Padding-Modifier und die Inset-Größen-Modifier, dass ein Teil der Insets bereits von äußeren Inset-Padding-Modifiern verwendet wurde. Sie vermeiden es, denselben Teil der Insets mehr als einmal zu verwenden, was zu viel zusätzlichem Leerraum führen würde.

Mit Größenmodifikatoren für Insets wird auch vermieden, dass derselbe Teil von Insets mehr als einmal verwendet wird, wenn Insets bereits verwendet wurden. Da sie ihre Größe jedoch direkt ändern, werden keine Insets verwendet.

Wenn Sie Padding-Modifier verschachteln, ändert sich automatisch die Menge an Padding, die auf die einzelnen Composables angewendet wird.

Im selben LazyColumn-Beispiel wie zuvor wird die Größe des LazyColumn mit dem Modifikator imePadding angepasst. Im LazyColumn wird das letzte Element so angepasst, dass es der Höhe des unteren Rands der Systemleisten entspricht:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Wenn die IME geschlossen ist, wird durch den imePadding()-Modifikator kein Padding angewendet, da die IME keine Höhe hat. Da für den Modifikator imePadding() kein Padding angewendet wird, werden keine Insets verwendet und die Höhe von Spacer entspricht der Größe der Unterseite der Systemleisten.

Wenn die IME geöffnet wird, werden die IME-Insets animiert, um der Größe der IME zu entsprechen, und der imePadding()-Modifikator beginnt, das untere Padding anzuwenden, um die Größe von LazyColumn beim Öffnen der IME anzupassen. Wenn der Modifikator imePadding() mit dem Anwenden des unteren Innenabstands beginnt, wird auch dieser Betrag an Insets verwendet. Daher beginnt die Höhe von Spacer zu sinken, da ein Teil des Abstands für die Systemleisten bereits durch den Modifikator imePadding() angewendet wurde. Wenn der Modifizierer imePadding() einen unteren Innenabstand anwendet, der größer als die Systemleisten ist, ist die Höhe von Spacer null.

Wenn die IME geschlossen wird, werden die Änderungen in umgekehrter Reihenfolge vorgenommen: Das Spacer beginnt, sich von einer Höhe von null zu erweitern, sobald das imePadding() weniger als die Unterseite der Systemleisten anwendet, bis das Spacer schließlich der Höhe der Unterseite der Systemleisten entspricht, wenn die IME vollständig animiert wurde.

Abbildung 2. Lazy Column mit TextField
, die sich über die gesamte Breite erstreckt.

Dieses Verhalten wird durch die Kommunikation zwischen allen windowInsetsPadding-Modifikatoren erreicht und kann auf verschiedene andere Arten beeinflusst werden.

Modifier.consumeWindowInsets(insets: WindowInsets) verwendet Insets auf dieselbe Weise wie Modifier.windowInsetsPadding, wendet die verwendeten Insets jedoch nicht als Padding an. Dies ist in Kombination mit den Modifikatoren für die Inset-Größe nützlich, um Geschwister-Elementen anzugeben, dass bereits eine bestimmte Anzahl von Insets verwendet wurde:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues) verhält sich sehr ähnlich wie die Version mit dem Argument WindowInsets, akzeptiert aber ein beliebiges PaddingValues. Das ist nützlich, um Kinder darüber zu informieren, wenn das Padding oder der Abstand durch einen anderen Mechanismus als die Inset-Padding-Modifikatoren bereitgestellt wird, z. B. durch ein normales Modifier.padding oder Spacer mit fester Höhe:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

Wenn die Rohwerte für die Fenstereinsätze ohne Verbrauch benötigt werden, verwenden Sie die WindowInsets-Werte direkt oder verwenden Sie WindowInsets.asPaddingValues(), um einen PaddingValues der Einsätze zurückzugeben, die nicht vom Verbrauch betroffen sind. Aufgrund der folgenden Einschränkungen sollten Sie jedoch nach Möglichkeit die Padding- und Größenmodifikatoren für Window Insets verwenden.

Insets und Jetpack Compose-Phasen

Compose verwendet die zugrunde liegenden AndroidX-Kern-APIs, um Insets zu aktualisieren und zu animieren. Diese APIs nutzen die zugrunde liegenden Plattform-APIs, die Insets verwalten. Aufgrund dieses Plattformverhaltens haben Insets eine besondere Beziehung zu den Phasen von Jetpack Compose.

Die Werte für Insets werden nach der Kompositionsphase, aber vor der Layoutphase aktualisiert. Das bedeutet, dass beim Lesen des Werts von Insets in einer Komposition in der Regel ein Wert der Insets verwendet wird, der einen Frame zu spät ist. Die auf dieser Seite beschriebenen integrierten Modifikatoren verzögern die Verwendung der Werte der Insets bis zur Layoutphase. So wird sichergestellt, dass die Inset-Werte für denselben Frame verwendet werden, für den sie aktualisiert werden.