WindowInsets ist die Standard-API in Jetpack Compose für die Verarbeitung von Bereichen des Bildschirms, die teilweise oder vollständig von der System-UI verdeckt werden. Zu diesen Bereichen gehören die Statusleiste, die Navigationsleiste und die Bildschirmtastatur. Alternativ können Sie vordefinierte WindowInsetsRulers wie SafeDrawing an Modifier.fitInside oder Modifier.fitOutside übergeben, um Ihre Inhalte an den Systemleisten und der Display-Aussparung auszurichten, oder benutzerdefinierte WindowInsetsRulers erstellen.
Vorteile von WindowInsetsRulers
- Vermeidet Komplexität bei der Nutzung: Es wird während der Platzierungsphase des Layouts ausgeführt. Dadurch wird die Inset-Verbrauchskette vollständig umgangen und es können immer die korrekten, absoluten Positionen von Systemleisten und Display-Aussparungen bereitgestellt werden, unabhängig davon, was übergeordnete Layouts getan haben. Die Methoden
Modifier.fitInsideoderModifier.fitOutsidesind hilfreich, um Probleme zu beheben, wenn übergeordnete Composables Insets fälschlicherweise nutzen. - Systemleisten einfach vermeiden: Damit können Sie verhindern, dass App-Inhalte von Systemleisten und der Display-Aussparung verdeckt werden. Das kann einfacher sein, als
WindowInsetsdirekt zu verwenden. - In hohem Maße anpassbar: Entwickler können Inhalte an benutzerdefinierten Linealen ausrichten und mit benutzerdefinierten Layouts die genaue Kontrolle über ihre Layouts behalten.
Nachteile von WindowInsetsRulers
- Kann nicht für die Messung verwendet werden: Da die API während der Platzierungsphase ausgeführt wird, sind die von ihr bereitgestellten Positionsinformationen während der früheren Messphase nicht verfügbar.
Inhalte mit Modifier-Methoden ausrichten
Mit Modifier.fitInside können Apps Inhalte an Systemleisten und Display-Aussparungen ausrichten. Sie kann anstelle von WindowInsets verwendet werden.
Modifier.fitOutside ist normalerweise das Gegenteil von Modifier.fitInside.
Mit fitInside(WindowInsetsRulers.safeDrawing.current) kannst du beispielsweise prüfen, ob App-Inhalte die Systemleisten und die Display-Aussparung umgehen.
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
In der folgenden Tabelle sehen Sie, wie Ihre App-Inhalte mit vordefinierten Linealen mit Modifier.fitInside oder Modifier.fitOutside aussehen würden.
| Vordefinierter Linealtyp | ||
|---|---|---|
![]() |
![]() |
|
![]() |
– |
|
![]() |
![]() |
|
![]() |
– (verwende stattdessen |
|
![]() |
![]() |
Wenn Sie Modifier.fitInside und Modifier.fitOutside verwenden, müssen die Composables eingeschränkt sein. Das bedeutet, dass Sie Modifikatoren wie Modifier.size oder Modifier.fillMaxSize definieren müssen.
Einige Lineale wie Modifier.fitOutside auf SafeDrawing und SystemBars geben mehrere Lineale zurück. In diesem Fall platziert Android das Composable mit einer Hilfslinie von links, oben, rechts und unten.
IME mit Modifier.fitInside vermeiden
Wenn du untere Elemente mit einer Eingabemethode mit Modifier.fitInside verarbeiten möchtest, übergib einen RectRuler, der den innersten Wert von NavigationBar und Ime annimmt.
@Composable fun FitInsideWithImeDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.NavigationBars.current, WindowInsetsRulers.Ime.current ) ) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier.align(Alignment.BottomStart).fillMaxWidth() ) } }
Statusleiste und Titelleiste mit Modifier.fitInside vermeiden
Wenn Sie prüfen möchten, ob die oberen Elemente die Statusleiste und die Titelleiste zusammen mit Modifier.fitInside vermeiden, übergeben Sie einen RectRuler, der den innersten Wert von StatusBars und CaptionBar verwendet.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
Benutzerdefinierte WindowInsetsRulers erstellen
Sie können Inhalte an benutzerdefinierten Linealen ausrichten. Ein Beispiel: Ein übergeordnetes Compose-Element verarbeitet Insets nicht richtig, was zu Padding-Problemen in einem untergeordneten Element führt. Dieses Problem kann zwar auch auf andere Weise gelöst werden, z. B. mit Modifier.fitInside, aber Sie können auch eine benutzerdefinierte Ausrichtungslinie erstellen, um die untergeordnete zusammensetzbare Funktion genau auszurichten, ohne das Problem im übergeordneten Element beheben zu müssen, wie im folgenden Beispiel und Video gezeigt:
@Composable fun WindowInsetsRulersDemo(modifier: Modifier) { Box( contentAlignment = BottomCenter, modifier = modifier .fillMaxSize() // The mistake that causes issues downstream, as .padding doesn't consume insets. // While it's correct to instead use .windowInsetsPadding(WindowInsets.navigationBars), // assume it's difficult to identify this issue to see how WindowInsetsRulers can help. .padding(WindowInsets.navigationBars.asPaddingValues()) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier // Use alignToSafeDrawing() instead of .imePadding() to precisely place this child // Composable without having to fix the parent upstream. .alignToSafeDrawing() // .imePadding() // .fillMaxWidth() ) } } fun Modifier.alignToSafeDrawing(): Modifier { return layout { measurable, constraints -> if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) { val placeable = measurable.measure(constraints) val width = placeable.width val height = placeable.height layout(width, height) { val bottom = WindowInsetsRulers.SafeDrawing.current.bottom .current(0f).roundToInt() - height val right = WindowInsetsRulers.SafeDrawing.current.right .current(0f).roundToInt() val left = WindowInsetsRulers.SafeDrawing.current.left .current(0f).roundToInt() measurable.measure(Constraints.fixed(right - left, height)) .place(left, bottom) } } else { val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { placeable.place(0, 0) } } } }
Das folgende Video zeigt ein Beispiel für eine problematische Nutzung von IME-Insets, die durch ein übergeordnetes Element im Bild links verursacht wird, und die Verwendung benutzerdefinierter Lineale, um das Problem im Bild rechts zu beheben. Unter dem TextField-Composable wird zusätzliches Padding angezeigt, da das Padding der Navigationsleiste nicht vom übergeordneten Element verwendet wurde. Das Kind wird im rechten Bild mithilfe eines benutzerdefinierten Lineals an der richtigen Stelle platziert, wie im vorherigen Codebeispiel zu sehen.
Prüfen, ob übergeordnete Elemente eingeschränkt sind
Damit WindowInsetsRulers sicher verwendet werden kann, muss das übergeordnete Element gültige Einschränkungen bereitstellen. Übergeordnete Elemente müssen eine definierte Größe haben und dürfen nicht von der Größe eines untergeordneten Elements abhängen, das WindowInsetsRulers verwendet. Verwenden Sie fillMaxSize oder andere Größenmodifikatoren für übergeordnete Composables.
Ebenso kann das Platzieren einer zusammensetzbaren Funktion, die WindowInsetsRulers verwendet, in einem scrollbaren Container wie verticalScroll zu unerwartetem Verhalten führen, da der scrollbare Container unbegrenzte Höhenbeschränkungen bietet, die mit der Logik des Lineals nicht kompatibel sind.







