WindowInsets é a API padrão no Jetpack Compose para processar
áreas da tela que estão parcial ou totalmente ocultas pela interface do sistema. Essas
áreas incluem a barra de status, a barra de navegação e o teclado na tela. Como alternativa,
você pode transmitir WindowInsetsRulers predefinidos, como
SafeDrawing, para Modifier.fitInside ou Modifier.fitOutside,
para alinhar o conteúdo com as barras de sistema e o corte da tela ou criar
WindowInsetsRulers personalizados.
Vantagens do WindowInsetsRulers
- Evita a complexidade de consumo: ele opera durante a fase de posicionamento
do layout. Isso significa que ele ignora completamente a cadeia de consumo de encartes e
pode sempre fornecer as posições absolutas corretas das barras de sistema e dos cortes
da tela, independente do que os layouts pai tenham feito. O uso dos
métodos
Modifier.fitInsideouModifier.fitOutsideé útil para corrigir problemas quando os elementos combináveis ancestrais consomem os encartes incorretamente. - Evitar facilmente as barras de sistema: ajuda o conteúdo do app a evitar as barras de sistema
e o corte da tela, além de ser mais simples do que usar
WindowInsetsdiretamente. - Altamente personalizável: os desenvolvedores podem alinhar o conteúdo a réguas personalizadas e ter controle preciso sobre os layouts com layouts personalizados.
Desvantagens do WindowInsetsRulers
- Não pode ser usado para medição: como ele opera durante a fase de posicionamento, as informações de posição que ele fornece não estão disponíveis durante a fase de medição anterior.
Alinhar o conteúdo com métodos modificadores
O Modifier.fitInside permite que os apps alinhem o conteúdo às barras de sistema e
aos cortes da tela. Ele pode ser usado em vez de WindowInsets.
Modifier.fitOutside geralmente é o inverso de Modifier.fitInside.
Por exemplo, para verificar se o conteúdo do app evita as barras de sistema e o corte da tela, use fitInside(WindowInsetsRulers.safeDrawing.current).
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
A tabela a seguir mostra como o conteúdo do app ficaria com réguas predefinidas
com Modifier.fitInside ou Modifier.fitOutside.
| Tipo de régua predefinido | ||
|---|---|---|
![]() |
![]() |
|
![]() |
N/A |
|
![]() |
![]() |
|
![]() |
N/A (use |
|
![]() |
![]() |
O uso de Modifier.fitInside e Modifier.fitOutside exige que os
elementos combináveis sejam restritos. Isso significa que você precisa definir modificadores como
Modifier.size ou Modifier.fillMaxSize.
Alguns governantes, como Modifier.fitOutside em SafeDrawing e SystemBars, retornam
vários governantes. Nesse caso, o Android posiciona o elemento combinável usando uma régua
da esquerda, de cima, da direita e de baixo.
Evitar o IME com Modifier.fitInside
Para processar elementos inferiores com um IME com Modifier.fitInside, transmita um
RectRuler que use o valor mais interno de NavigationBar e Ime.
@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() ) } }
Evitar a barra de status e a barra de legenda com Modifier.fitInside
Da mesma forma, para verificar se os elementos superiores evitam a barra de status e a barra de legenda junto
com Modifier.fitInside, transmita um RectRuler que use o valor mais interno de
StatusBars e CaptionBar.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
Criar WindowInsetsRulers personalizado
É possível alinhar o conteúdo a réguas personalizadas. Por exemplo, considere o caso de uso em que
um elemento combinável pai processa as inserções de forma inadequada, causando problemas de padding em um
filho downstream. Embora esse problema possa ser resolvido de outras maneiras, incluindo o
uso de Modifier.fitInside, você também pode criar uma régua personalizada para alinhar
com precisão o elemento combinável filho sem precisar corrigir o problema no elemento pai
upstream, conforme mostrado no exemplo e no vídeo a seguir:
@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) } } } }
O vídeo a seguir mostra um exemplo de consumo problemático de inserção de IME
causado por um pai upstream na imagem à esquerda e o uso de réguas personalizadas
para corrigir o problema à direita. O padding extra é mostrado abaixo do elemento combinável
TextField, já que o padding da barra de navegação não foi consumido pelo pai. O
filho é colocado no local correto na imagem à direita usando uma régua personalizada,
conforme mostrado no exemplo de código anterior.
Verificar se os pais estão restritos
Para usar WindowInsetsRulers com segurança, verifique se o pai fornece restrições
válidas. Os pais precisam ter um tamanho definido e não podem depender do tamanho de um
filho que usa WindowInsetsRulers. Use fillMaxSize ou outros modificadores de tamanho
em elementos combináveis pai.
Da mesma forma, colocar um elemento combinável que usa WindowInsetsRulers dentro de um
contêiner de rolagem, como verticalScroll, pode causar um comportamento inesperado, já que o
contêiner de rolagem oferece restrições de altura ilimitadas, que são
incompatíveis com a lógica da régua.







