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 sie 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 Einzüge für die Statusleiste beispielsweise 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 Überschneidungen mit dieser Art von System-UI zu vermeiden, muss die App-UI um diesen Betrag eingerückt sein.
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 die Navigationssymbole beschreiben. Diese können sich zur Laufzeit ändern, je nachdem, welche Navigationsmethode der Nutzer bevorzugt und wie er mit der Taskleiste interagiert. |
|
Die Navigationsleiste wird eingerückt, wenn sie sichtbar ist. 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 der 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 |
|
Ein Teil der Systemgesten, die immer vom System verarbeitet 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 Einzüge, die die gekrümmten Bereiche eines Kaskadenaufrufs 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:
- Verwenden Sie
WindowInsets.safeDrawing
, um Inhalte zu schützen, die nicht unter der Benutzeroberfläche des Systems dargestellt werden sollen. Dies ist die häufigste Verwendung von Einblendungen: Sie verhindern das Zeichnen von Inhalten, die teilweise oder vollständig von der System-UI verdeckt werden. - Verwenden Sie
WindowInsets.safeGestures
, um Inhalte mit Touch-Gesten zu schützen. So wird verhindert, dass System-Gesten mit App-Gesten kollidieren, z. B. mit denen für Infofelder, Karussells oder in Spielen. - Verwenden Sie
WindowInsets.safeContent
als Kombination ausWindowInsets.safeDrawing
undWindowInsets.safeGestures
, damit sich Inhalte nicht überschneiden und es keine Überschneidungen bei Gesten gibt.
Einzüge einrichten
Wenn Sie Ihrer App die vollständige Kontrolle darüber geben möchten, wo Inhalte dargestellt werden, folgen Sie dieser Einrichtungsanleitung. 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">
APIs erstellen
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 können Sie beispielsweise die Einblendungen auf den Inhalt Ihrer gesamten App anwenden:
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 Rand-zu-Rand-Effekt 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 Einzüge verwendet werden, 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
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 selbst 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. Hier wird die Größe von LazyColumn
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, beim Öffnen der IME einen unteren Abstand anzuwenden, um die Größe von LazyColumn
zu ändern. 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 anwendet, 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.
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. Das ist nützlich, um Kinder darüber zu informieren, wenn 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 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.
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") } } }
Unterstützung für Einzüge bei 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
Einzüge als Parameter paddingValues
bereit, die Sie 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 an das Composeable übergebenen Parameter windowInsets
ändern, um das Verhalten des Composeable zu konfigurieren. Mit diesem Parameter kann ein anderer Fenstereinzug 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 Standard-Einzüge überschreiben, wenn sich auf Ihrem Bildschirm sowohl Ansichten als auch Compose-Code in derselben Hierarchie befinden. 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 von jedem ComposeView
alle Inset-Assets auf der Verbrauchsebene WindowInsetsCompat
verbraucht. 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 ist jedoch durchscheinend.
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
- Android-Systemleisten, Designleitfaden für Systemleisten
- Jetzt bei Android: eine voll funktionsfähige Android-App, die vollständig mit Kotlin und Jetpack Compose entwickelt wurde.
- Edge-to-Edge-Erzwungenheiten in Android 15 verarbeiten – Codelab zur Edge-to-Edge-Erzwungenheit in Android 15
- Tipps zur Verarbeitung von Rändern für die Vollbildansicht von 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
- Edge-to-Edge and Insets | Compose Tips – ein YouTube-Video, in dem gezeigt wird, wie Sie mit Einzügen arbeiten, um Bilder bis zum Rand zu zeichnen
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Materialkomponenten und -layouts
CoordinatorLayout
zu Compose migrieren- Weitere Hinweise