Sorgen Sie dafür, dass Ihre Benutzeroberfläche mit Fenstereinblendungen funktioniert

Sobald Ihre Aktivität die Verarbeitung aller Einblendungen übernommen hat, können Sie mit Compose APIs dafür sorgen, dass Inhalte nicht verdeckt und interaktive Elemente nicht mit der System-UI überlappen. Diese APIs synchronisieren auch das Layout Ihrer App mit Änderungen am Insert.

So wenden Sie die Einblendungen beispielsweise auf den Inhalt Ihrer gesamten App an:

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

    enableEdgeToEdge()

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

In diesem Snippet werden die Fenstereinzüge safeDrawing als Abstand um den gesamten Inhalt der App herum angewendet. Dadurch wird sichergestellt, dass sich interaktive Elemente nicht mit der System-UI überschneiden. Es bedeutet aber auch, dass keine App-Inhalte hinter der System-UI gezeichnet werden, um einen Randeffekt zu erzielen. Damit Sie das gesamte Fenster optimal nutzen können, müssen Sie die Platzierung der Einblendungen auf Bildschirm- oder Komponentenebene optimieren.

Alle diese Einblendungstypen werden automatisch mit IME-Animationen animiert, die auf API 21 zurückportiert wurden. Alle Layouts, in denen diese Einzüge verwendet werden, werden ebenfalls automatisch animiert, wenn sich die Einzugswerte ändern.

Es gibt zwei Hauptmethoden, mit denen Sie diese Arten von Einzügen verwenden können, um Ihre zusammensetzbaren Layouts anzupassen: Padding-Modifikatoren und Modifikatoren für die Einzuggröße.

Ränder

Mit Modifier.windowInsetsPadding(windowInsets: WindowInsets) werden die angegebenen Fenstereinzüge als Abstand angewendet, genau wie bei Modifier.padding. Bei Modifier.windowInsetsPadding(WindowInsets.safeDrawing) werden die sicheren Zeichenbereiche beispielsweise als Abstand auf allen vier Seiten angewendet.

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

Modifikatoren für die Größe des Einzugs

Mit den folgenden Modifikatoren können Sie die Größe der Fensterausschnitte festlegen, indem Sie die Größe der Komponente auf die Größe der Ausschnitte festlegen:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

Die Startseite von „windowInsets“ wird als Breite angewendet (z. B. Modifier.width).

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

Die Endseite von „windowInsets“ wird als Breite angewendet (z. B. Modifier.width).

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

Die Oberseite von „windowInsets“ wird als Höhe angewendet (z. B. Modifier.height).

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

Die untere Seite von „windowInsets“ wird als Höhe angewendet (z. B. Modifier.height).

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

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

Einblendung

Die Modifikatoren für den Abstand von Einzügen (windowInsetsPadding und Hilfselemente wie safeDrawingPadding) verbrauchen automatisch den Teil der Einzüge, der als Abstand angewendet wird. Wenn Sie tiefer in den Kompositionbaum eindringen, wissen verschachtelte Modifikatoren für den Abstand von Einzügen und die Größe von Einzügen, dass ein Teil der Einzüge bereits durch Modifikatoren für den Abstand von äußeren Einzügen belegt wurde. Sie vermeiden es, denselben Teil der Einzüge mehrmals zu verwenden, was zu zu viel zusätzlichem Platz führen würde.

Mithilfe von Modifikatoren für die Größe von Einzügen wird außerdem verhindert, dass derselbe Teil von Einzügen mehrmals verwendet wird, wenn Einzüge bereits verwendet wurden. Da sie ihre Größe jedoch direkt ändern, belegen sie keine Einzüge.

Durch das Verschachteln von Padding-Modifizierern wird also automatisch die Größe des Paddings für jedes Composeable geändert.

Sehen wir uns das Beispiel mit LazyColumn noch einmal an. Die Größe von LazyColumn wird durch den Modifikator imePadding geändert. Innerhalb von LazyColumn hat das letzte Element die Höhe des unteren Endes der Systemleisten:

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

Wenn die IME geschlossen ist, wird mit dem imePadding()-Modifikator kein Abstand angewendet, da die IME keine Höhe hat. Da mit dem imePadding()-Modifikator kein Abstand angewendet wird, werden keine Einzüge verwendet und die Höhe der Spacer entspricht der Größe der Unterseite der Systemleisten.

Wenn die IME geöffnet wird, werden die Einzüge der IME animiert, um der Größe der IME zu entsprechen. Der Modifikator imePadding() beginnt dann, einen unteren Abstand anzuwenden, um die Größe der LazyColumn zu ändern, während die IME geöffnet wird. Sobald der imePadding()-Modifikator das untere Padding anwendet, wird auch diese Menge an Einzügen verbraucht. Daher beginnt die Höhe des Spacer zu sinken, da ein Teil des Abstands für die Systemleisten bereits durch den imePadding()-Modifikator angewendet wurde. Wenn der imePadding()-Modifikator einen Abstand nach unten festlegt, der größer als die Systemleisten ist, ist die Höhe von Spacer 0.

Wenn die IME geschlossen wird, werden die Änderungen in umgekehrter Reihenfolge ausgeführt: Die Spacer beginnt, sich von einer Höhe von null auszudehnen, sobald die imePadding() kleiner als die untere Seite der Systemleisten ist, bis die Spacer schließlich die Höhe der unteren Seite der Systemleisten erreicht, sobald die IME vollständig ausgeblendet ist.

Abbildung 2. Lazy-Spalte von Rand zu Rand mit TextField

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

Modifier.consumeWindowInsets(insets: WindowInsets) verbraucht Einzüge auf dieselbe Weise wie Modifier.windowInsetsPadding, wendet sie aber nicht als Abstand an. Das ist in Kombination mit den Modifikatoren für die Größe des Einzugs nützlich, um Geschwistern anzugeben, dass bereits eine bestimmte Anzahl von Einzügen 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, nimmt aber ein beliebiges PaddingValues zum Verbrauch an. Dies ist nützlich, um Kinder darüber zu informieren, dass Ränder oder Abstände durch einen anderen Mechanismus als die Modifikatoren für den Abstand zum Textfeld bereitgestellt werden, z. B. durch einen normalen Modifier.padding oder durch Abstände mit fester Höhe:

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

Wenn die Rohfenster-Inset-Werte ohne Verbrauch benötigt werden, verwenden Sie die WindowInsets-Werte direkt oder WindowInsets.asPaddingValues(), um eine PaddingValues der Inset-Werte zurückzugeben, die nicht von der Nutzung betroffen sind. Aufgrund der folgenden Einschränkungen sollten Sie jedoch nach Möglichkeit die Modifikatoren für den Abstand und die Größe der Fenstereinzüge verwenden.

Ränder und Jetpack Compose-Phasen

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

Der Wert von „insets“ wird nach der Komposition, aber vor der Layoutphase aktualisiert. Das bedeutet, dass beim Lesen des Werts der Einblendungen in der Komposition in der Regel ein Wert der Einblendungen verwendet wird, der um einen Frame verzögert ist. Die auf dieser Seite beschriebenen integrierten Modifikatoren verzögern die Verwendung der Werte der Einzüge bis zur Layoutphase. So wird sichergestellt, dass die Einzugswerte im selben Frame verwendet werden, in dem sie aktualisiert werden.