Die Android-Plattform ist für das Zeichnen der System-UI wie der Statusleiste und der Navigationsleiste verantwortlich. Diese System-UI wird unabhängig davon angezeigt, welche App der Nutzer verwendet.
WindowInsets
enthält Informationen zur System-UI, damit Ihre App im richtigen Bereich gezeichnet wird und Ihre Benutzeroberfläche nicht von der System-UI verdeckt wird.
Unter Android 14 (API-Level 34) und niedriger wird die Benutzeroberfläche Ihrer App standardmäßig nicht unter den Systemleisten und Displayausschnitten gezeichnet.
Unter Android 15 (API-Level 35) und höher wird Ihre App unter den Systemleisten und Displayausschnitten dargestellt, wenn Ihre App auf SDK 35 ausgerichtet ist. Das führt zu einer besseren Nutzererfahrung und ermöglicht es Ihrer App, den gesamten verfügbaren Fensterbereich zu nutzen.
Wenn Inhalte hinter der System-UI angezeigt werden, wird dies als Bildschirmrand-zu-Bildschirmrand-Ansicht bezeichnet. Auf dieser Seite erfahren Sie mehr über die verschiedenen Arten von Einblendungen, wie Sie den gesamten Bildschirm nutzen und wie Sie die Einblendungs-APIs verwenden, um Ihre Benutzeroberfläche zu animieren und dafür zu sorgen, dass die Inhalte Ihrer App nicht von System-UI-Elementen verdeckt werden.
Grundlegendes zu Einblendungen
Wenn eine App den gesamten Bildschirm einnimmt, müssen Sie darauf achten, dass wichtige Inhalte und Interaktionen nicht von der System-UI verdeckt werden. Wenn eine Schaltfläche beispielsweise hinter der Navigationsleiste platziert ist, kann der Nutzer möglicherweise nicht darauf klicken.
Die Größe der System-UI und Informationen zur Platzierung werden über Einzüge angegeben.
Jeder Bereich der System-UI hat einen entsprechenden Einleger, der seine Größe und Position beschreibt. So geben beispielsweise Einzüge für die Statusleiste die Größe und Position der Statusleiste an, während Einzüge für die Navigationsleiste die Größe und Position der Navigationsleiste angeben. Jeder Art von Einleger werden vier Pixelabmessungen zugewiesen: oben, links, rechts und unten. Diese Abmessungen geben an, wie weit sich die System-UI von den entsprechenden Seiten des App-Fensters erstreckt. Um eine Überschneidung mit diesem Typ von System-UI zu vermeiden, muss die Anwendungs-UI daher in diesem Betrag eingesetzt werden.
Diese integrierten Android-Einblendungstypen sind über WindowInsets
verfügbar:
Die Einblendungen, die die Statusleisten beschreiben. Das sind die oberen System-UI-Leisten mit Benachrichtigungssymbolen und anderen Indikatoren. |
|
Die Statusleiste wird eingerückt, wenn sie sichtbar ist. Wenn die Statusleisten derzeit ausgeblendet sind (weil der immersive Vollbildmodus aktiviert ist), sind die Einzüge der Hauptstatusleiste leer. |
|
Die Einblendungen, in denen die Navigationsleisten beschrieben werden. Dies sind die System-UI-Leisten auf der linken, rechten oder unteren Seite des Geräts, die die Taskleiste oder Navigationssymbole beschreiben. Diese können sich zur Laufzeit ändern, je nachdem, welche Navigationsmethode der Nutzer bevorzugt und wie er mit der Taskleiste interagiert. |
|
Die Navigationsleisteneinfügungen für den Zeitpunkt, an dem sie sichtbar sind. Wenn die Navigationsleisten derzeit ausgeblendet sind (weil der immersive Vollbildmodus aktiviert ist), sind die Einzüge der Hauptnavigationsleiste leer. |
|
Der Einschub, der die Fensterdekoration der System-UI beschreibt, wenn sich das Fenster in einem freiformigen Fenster befindet, z. B. die obere Titelleiste. |
|
Die Untertitelleiste wird eingeblendet, wenn sie sichtbar ist. Wenn die Untertitelleisten derzeit ausgeblendet sind, sind die Einzüge der Hauptuntertitelleiste leer. |
|
Die Vereinigung der Systemleisten, einschließlich Statusleisten, Navigationsleisten und Titelleisten. |
|
Die Systemleiste wird eingeblendet, wenn sie sichtbar ist. Wenn die Systemleisten derzeit ausgeblendet sind (weil der immersive Vollbildmodus aktiviert ist), sind die Einzüge der Hauptsystemleiste leer. |
|
Die Einzüge, die den Platz unten beschreiben, den die Softwaretastatur einnimmt. |
|
Die Einblendungen, die den Platz beschreiben, den die Softwaretastatur vor der aktuellen Tastaturanimation belegt hat. |
|
Die Einzüge, die den Platz beschreiben, den die Softwaretastatur nach der aktuellen Tastaturanimation einnimmt. |
|
Eine Art von Einblendungen, die detailliertere Informationen zur Navigations-UI enthalten und den Bereich angeben, in dem „Tippen“ vom System und nicht von der App verarbeitet wird. Bei transparenten Navigationsleisten mit Gestennavigation können einige App-Elemente über die Systemnavigations-UI angetippt werden. |
|
Die anklickbaren Elemente werden eingeblendet, wenn sie sichtbar sind. Wenn die anklickbaren Elemente derzeit ausgeblendet sind (z. B. weil der immersive Vollbildmodus aktiviert ist), sind die Einzüge der Hauptelemente leer. |
|
Die Einzüge, die die Anzahl der Einzüge darstellen, bei denen das System Touch-Gesten für die Navigation abfängt. Apps können die Verarbeitung einer begrenzten Anzahl dieser Touch-Gesten über |
|
Eine Untergruppe der Systemgesten, die immer vom System ausgeführt werden und die nicht über |
|
Die Einzüge, die den Abstand darstellen, der erforderlich ist, um Überschneidungen mit einem Displayausschnitt (Notch oder Loch) zu vermeiden. |
|
Die Einsätze, die die gekrümmten Bereiche einer Wasserfalldarstellung darstellen. Ein Waterfall-Display hat an den Rändern des Displays gekrümmte Bereiche, in denen das Display an den Seiten des Geräts umgeschlagen wird. |
Diese Typen werden in drei „sichere“ Einblendungstypen zusammengefasst, die dafür sorgen, dass Inhalte nicht verdeckt werden:
Diese „sicheren“ Einbettungstypen schützen Inhalte je nach zugrunde liegender Plattform auf unterschiedliche Weise:
- Mit
WindowInsets.safeDrawing
können Sie Inhalte schützen, die nicht unter einer System-UI angezeigt werden sollen. Dies ist die häufigste Verwendung von Einfügungen: Sie dient dazu, das Zeichnen von Inhalten zu verhindern, die teilweise oder vollständig von der System-UI verdeckt werden. - Verwenden Sie
WindowInsets.safeGestures
, um Inhalte mit Gesten zu schützen. Dadurch wird vermieden, dass Systembewegungen mit App-Gesten in Konflikt geraten, z. B. für Ansichten am unteren Rand, Karussells oder in Spielen. - Verwende
WindowInsets.safeContent
in Kombination ausWindowInsets.safeDrawing
undWindowInsets.safeGestures
, damit Inhalte keine visuelle oder Gestenüberschneidung haben.
Einzüge einrichten
Wenn Sie Ihrer App die vollständige Kontrolle darüber geben möchten, wo Inhalte dargestellt werden, folgen Sie dieser Anleitung. Ohne diese Schritte wird in Ihrer App möglicherweise schwarz oder eine durchgehende Farbe hinter der System-UI gezeichnet oder die Animation erfolgt nicht synchron mit der Softwaretastatur.
- Richten Sie Ihre App auf SDK 35 oder höher aus, um unter Android 15 und höher Vollbildanzeigen zu erzwingen. Ihre App wird hinter der System-UI angezeigt. Sie können die Benutzeroberfläche Ihrer App anpassen, indem Sie Einblendungen verwenden.
- Optional können Sie
enableEdgeToEdge()
inActivity.onCreate()
aufrufen, damit Ihre App in älteren Android-Versionen randlos angezeigt wird. Lege
android:windowSoftInputMode="adjustResize"
imAndroidManifest.xml
-Eintrag deiner Aktivität fest. Mit dieser Einstellung kann Ihre App die Größe der Software-IME als Einzüge erhalten. So können Sie Inhalte entsprechend auffüllen und layouten, wenn die IME in Ihrer App erscheint und verschwindet.<!-- in your AndroidManifest.xml file: --> <activity android:name=".ui.MainActivity" android:label="@string/app_name" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.MyApplication" android:exported="true">
Compose-APIs
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 den Ä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. Außerdem werden alle Layouts, in denen diese Einfügungen verwendet werden, automatisch animiert, wenn sich die eingefügten Werte ändern.
Es gibt zwei Hauptmethoden, mit denen Sie diese Einblendungstypen verwenden können, um Ihre zusammensetzbaren Layouts anzupassen: Padding-Modifikatoren und Modifikatoren für die Einblendungsgröße.
Ränder
Bei 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 Einblendungen 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:
Die Startseite von „windowInsets“ wird als Breite angewendet (z. B. |
|
Die Endseite von „windowInsets“ wird als Breite angewendet (z. B. |
|
Die Oberseite von „windowInsets“ wird als Höhe angewendet (z. B. |
|
|
Die untere Seite von „windowInsets“ wird als Höhe angewendet (z. B. |
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 verschachtelte Padding-Modifikatoren wird daher automatisch die Größe des Paddings für jedes Composeable geändert.
Im selben LazyColumn
-Beispiel wie zuvor wird die Größe von LazyColumn
durch den imePadding
-Modifikator 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 der IME geöffnet wird, werden die IME-Einsätze entsprechend der Größe des IME animiert und der imePadding()
-Modifikator wendet einen Abstand unten an, um die Größe von LazyColumn
anzupassen, wenn der 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
dehnt sich von einer Höhe von null aus, sobald die imePadding()
kleiner als die untere Seite der Systemleisten ist, bis die Spacer
schließlich der Höhe der unteren Seite der Systemleisten entspricht, sobald die IME vollständig ausgeblendet ist.
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 einem WindowInsets
-Argument, verwendet aber ein beliebiges PaddingValues
zur Verarbeitung. Das 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 vom Verbrauch betroffen sind.
Aufgrund der nachfolgenden Vorbehalte sollten Sie jedoch nach Möglichkeit die Padding-Modifikatoren für Fenstereinfügungen und die Größenmodifikatoren für Fenstereinfügungen 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.
IME-Animationen der Tastatur mit WindowInsets
Sie können Modifier.imeNestedScroll()
auf einen scrollbaren Container anwenden, um die IME automatisch zu öffnen und zu schließen, wenn Sie zum Ende des Containers scrollen.
class WindowInsetsExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) setContent { MaterialTheme { MyScreen() } } } } @OptIn(ExperimentalLayoutApi::class) @Composable fun MyScreen() { Box { LazyColumn( modifier = Modifier .fillMaxSize() // fill the entire window .imePadding() // padding for the bottom for the IME .imeNestedScroll(), // scroll IME at the bottom content = { } ) FloatingActionButton( modifier = Modifier .align(Alignment.BottomEnd) .padding(16.dp) // normal 16dp of padding for FABs .navigationBarsPadding() // padding for navigation bar .imePadding(), // padding for when IME appears onClick = { } ) { Icon(imageVector = Icons.Filled.Add, contentDescription = "Add") } } }
Eingefügte Unterstützung für Material 3-Komponenten
Für eine einfache Bedienung werden Einzüge bei vielen der integrierten Material 3-Kompositionen (androidx.compose.material3
) automatisch verwaltet. Dabei wird berücksichtigt, wie die Kompositionen gemäß den Material-Spezifikationen in Ihrer App platziert werden.
Einfügen von Composeable-Elementen
Unten finden Sie eine Liste der Materialkomponenten, die Einzüge automatisch verarbeiten.
App-Leisten
TopAppBar
/SmallTopAppBar
/CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: Die obere und horizontale Seite der Systemleisten werden als Abstand angewendet, da sie oben im Fenster verwendet wird.BottomAppBar
: Hiermit werden die untere und die horizontale Seite der Systemleisten als Abstand verwendet.
Content-Container
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(Inhalte in einer modalen Navigationsleiste): Hier werden die Einzüge vertikal und start auf die Inhalte angewendet.ModalBottomSheet
: Mit dieser Option werden die Unterschnitte angewendet.NavigationBar
: Wendet die Einzüge bottom (unten) und horizontal (horizontal) an.NavigationRail
: Wendet die Einzüge vertikal und start an.
Gerüst
Standardmäßig stellt Scaffold
Einfügungen als Parameter paddingValues
bereit, die Sie nutzen und verwenden können.
Scaffold
wendet die Einblendungen nicht auf Inhalte an. Dafür sind Sie selbst verantwortlich.
So verwenden Sie diese Einzüge beispielsweise mit einem LazyColumn
in einem Scaffold
:
Scaffold { innerPadding -> // innerPadding contains inset information for you to use and apply LazyColumn( // consume insets as scaffold doesn't do it by default modifier = Modifier.consumeWindowInsets(innerPadding), contentPadding = innerPadding ) { items(count = 100) { Box( Modifier .fillMaxWidth() .height(50.dp) .background(colors[it % colors.size]) ) } } }
Standard-Einzüge überschreiben
Sie können den Parameter windowInsets
, der an die zusammensetzbare Funktion übergeben wird, ändern, um das Verhalten der zusammensetzbaren Funktion zu konfigurieren. Mit diesem Parameter kann ein anderer Fenster-Einsetztyp angewendet oder deaktiviert werden, indem eine leere Instanz übergeben wird: WindowInsets(0, 0, 0, 0)
.
Wenn Sie beispielsweise die Einzug-Verarbeitung für LargeTopAppBar
deaktivieren möchten, setzen Sie den Parameter windowInsets
auf eine leere Instanz:
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
Interoperabilität mit den Ansichts-Einblendungen
Möglicherweise müssen Sie die Standardeinfügungen überschreiben, wenn auf Ihrem Bildschirm sowohl Aufruf- als auch Editor-Code in derselben Hierarchie vorhanden sind. In diesem Fall müssen Sie angeben, welche der beiden Seiten die Einleger verwenden und welche sie ignorieren soll.
Wenn Ihr äußerstes Layout beispielsweise ein Android-View-Layout ist, sollten Sie die Einzüge im View-System verwenden und für Compose ignorieren.
Wenn Ihr äußerstes Layout ein Composeable ist, sollten Sie die Einzüge in Compose verwenden und die AndroidView
-Composeables entsprechend ausrichten.
Standardmäßig werden für jede ComposeView
alle Inset-Assets auf der Verbrauchsebene WindowInsetsCompat
verwendet. Wenn Sie dieses Standardverhalten ändern möchten, setzen Sie ComposeView.consumeWindowInsets
auf false
.
Schutz der Systemleiste
Sobald Ihre App auf SDK 35 oder höher ausgerichtet ist, wird Edge-to-Edge erzwungen. Die Systemstatusleiste und die Navigationsleisten für Gesten sind transparent, die Navigationsleiste mit drei Schaltflächen hingegen durchsichtig.
Wenn Sie den standardmäßigen halbtransparenten Hintergrundschutz für die Navigation mit drei Schaltflächen entfernen möchten, setzen Sie Window.setNavigationBarContrastEnforced
auf false
.
Ressourcen
- Jetzt bei Android: eine voll funktionsfähige Android-App, die vollständig mit Kotlin und Jetpack Compose entwickelt wurde.
- Edge-to-Edge-Erzwingung in Android 15 – ein Codelab zur Edge-to-Edge-Erzwingung von Android 15
- Tipps zur Verarbeitung von Rändern für die Vollbildansicht in Android 15
- Vollbild-UI Ihrer App in der Vorschau ansehen und testen
- 3 Dinge, die Ihre Android-App verbessern: Vollbild, Vorhersagefunktion für die Rückwärtsnavigation und Glance – ein YouTube-Video zur Vollbildansicht in Android 15
- Rand-to-Edge und Insets | Compose Tips (Tipps zum Schreiben) – Ein YouTube-Video, in dem gezeigt wird, wie Insets von Rand zu Rand gezeichnet werden
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Materialkomponenten und -layouts
CoordinatorLayout
zu Compose migrieren- Weitere Hinweise