WindowInsets è l'API standard in Jetpack Compose per la gestione delle aree dello schermo parzialmente o completamente oscurate dall'UI di sistema. Queste aree includono la barra di stato, la barra di navigazione e la tastiera sullo schermo. In alternativa, puoi
passare WindowInsetsRulers predefiniti come SafeDrawing a
Modifier.fitInside o Modifier.fitOutside per allineare i contenuti
alle barre di sistema e al ritaglio display o creare WindowInsetsRulers personalizzati.
Vantaggi di WindowInsetsRulers
- Evita la complessità del consumo: funziona durante la fase di posizionamento
del layout. Ciò significa che bypassa completamente la catena di consumo degli inset e può sempre fornire le posizioni assolute corrette delle barre di sistema e dei ritagli del display, indipendentemente da ciò che hanno fatto i layout principali. L'utilizzo dei metodi
Modifier.fitInsideoModifier.fitOutsideè utile per risolvere i problemi quando i composable predecessori consumano in modo errato gli inset. - Evita facilmente le barre di sistema: aiuta i contenuti dell'app a evitare le barre di sistema
e il ritaglio display e può essere più semplice rispetto all'utilizzo diretto di
WindowInsets. - Altamente personalizzabile: gli sviluppatori possono allineare i contenuti a righelli personalizzati e avere un controllo preciso sui layout con layout personalizzati.
Svantaggi di WindowInsetsRulers
- Non può essere utilizzato per la misurazione: poiché funziona durante la fase di posizionamento, le informazioni sulla posizione che fornisce non sono disponibili durante la fase di misurazione precedente.
Allinea i contenuti con i metodi Modifier
Modifier.fitInside consente alle app di allineare i contenuti alle barre di sistema e ai ritagli del display. Può essere utilizzato al posto di WindowInsets. Modifier.fitOutside è in genere l'inverso di Modifier.fitInside.
Ad esempio, per verificare che i contenuti dell'app evitino le barre di sistema e il ritaglio del display, puoi utilizzare fitInside(WindowInsetsRulers.safeDrawing.current).
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
La tabella seguente mostra l'aspetto dei contenuti dell'app con i righelli predefiniti con Modifier.fitInside o Modifier.fitOutside.
| Tipo di righello predefinito | ||
|---|---|---|
![]() |
![]() |
|
![]() |
N/D |
|
![]() |
![]() |
|
![]() |
N/D (utilizza invece |
|
![]() |
![]() |
L'utilizzo di Modifier.fitInside e Modifier.fitOutside richiede che i composable siano vincolati. Ciò significa che devi definire modificatori come Modifier.size o Modifier.fillMaxSize.
Alcuni righelli come Modifier.fitOutside su SafeDrawing e SystemBars restituiscono più righelli. In questo caso, Android posiziona il componibile utilizzando un righello da sinistra, in alto, a destra, in basso.
Evita l'IME con Modifier.fitInside
Per gestire gli elementi inferiori con un IME con Modifier.fitInside, passa un RectRuler che accetta il valore più interno di 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() ) } }
Evita la barra di stato e la barra delle didascalie con Modifier.fitInside
Allo stesso modo, per verificare che gli elementi superiori evitino la barra di stato e la barra delle didascalie insieme a Modifier.fitInsider, passa un RectRuler che accetta il valore più interno di StatusBars e CaptionBar.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
Crea WindowInsetsRulers personalizzati
Puoi allineare i contenuti a righelli personalizzati. Prendi in considerazione, ad esempio, il caso d'uso in cui un composable principale gestisce in modo errato gli inset, causando problemi di padding in un elemento secondario a valle. Sebbene questo problema possa essere risolto in altri modi, incluso l'utilizzo di Modifier.fitInside, puoi anche creare un righello personalizzato per allineare con precisione il composable secondario senza dover risolvere il problema nel composable principale a monte, come mostrato nell'esempio e nel video seguenti:
@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) } } } }
Il video seguente mostra un esempio di consumo problematico degli inset IME causato da un elemento principale a monte nell'immagine a sinistra e l'utilizzo di righelli personalizzati per risolvere il problema a destra. Sotto il composable TextField viene mostrato un padding aggiuntivo perché il padding della barra di navigazione non è stato consumato dall'elemento principale. Nell'immagine a destra, l'elemento secondario viene posizionato nella posizione corretta utilizzando un righello personalizzato, come mostrato nell'esempio di codice precedente.
Verifica che gli elementi principali siano vincolati
Per utilizzare in sicurezza WindowInsetsRulers, assicurati che l'elemento principale fornisca vincoli validi. Gli elementi principali devono avere una dimensione definita e non possono dipendere dalla dimensione di un elemento secondario che utilizza WindowInsetsRulers. Utilizza fillMaxSize o altri modificatori di dimensione nei composable principali.
Allo stesso modo, l'inserimento di un composable che utilizza WindowInsetsRulers all'interno di un container di scorrimento come verticalScroll può causare un comportamento imprevisto, poiché il container di scorrimento fornisce vincoli di altezza illimitati, che non sono compatibili con la logica del righello.







