WindowInsets
è l'API standard in Jetpack Compose per la gestione
delle aree dello schermo parzialmente o completamente oscurate dalla UI di sistema. Queste
aree includono la barra di stato, la barra di navigazione e la tastiera sullo schermo. In alternativa, puoi
trasmettere WindowInsetsRulers
predefiniti come SafeDrawing
a
Modifier.fitInside
o Modifier.fitOutside
per allineare i contenuti
alle barre di sistema e al ritaglio del display o creare
WindowInsetsRulers
personalizzati.
Vantaggi di WindowInsetsRulers
- Evita la complessità del consumo: opera durante la fase di posizionamento
del layout. Ciò significa che bypassa completamente la catena di consumo degli inset e
può sempre fornire le posizioni corrette e assolute delle barre di sistema e dei
ritagli del display, indipendentemente da ciò che hanno fatto i layout principali. L'utilizzo dei metodi
Modifier.fitInside
oModifier.fitOutside
è utile per risolvere i problemi quando i composable antenati consumano in modo errato gli inset. - Evita facilmente le barre di sistema: aiuta i contenuti dell'app a evitare le barre di sistema e l'intaglio del display e può essere più semplice dell'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é opera durante la fase di posizionamento, le informazioni posizionali che fornisce non sono disponibili durante la fase di misurazione precedente.
- Potenziale instabilità del layout: ciò può causare arresti anomali se le dimensioni di un layout principale dipendono dalle dimensioni dei relativi elementi secondari. Poiché un elemento secondario che utilizza
WindowInsetsRulers
potrebbe cambiare posizione o dimensioni durante il posizionamento, può creare un ciclo di layout instabile.
Crea WindowInsetsRulers
personalizzato
Puoi allineare i contenuti a righelli personalizzati. Ad esempio, considera il caso d'uso in cui
un composable padre gestisce in modo errato gli inset causando problemi di spaziatura interna in un
elemento secondario downstream. Sebbene questo problema possa essere risolto in altri modi, ad esempio utilizzando Modifier.fitInside
, puoi anche creare un righello personalizzato per allineare con precisione il composable figlio senza dover risolvere il problema nel composable padre upstream, 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 seguente video mostra un esempio di consumo problematico dell'inserimento IME
causato da un elemento principale upstream 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 utilizzato dal genitore. L'elemento
figlio viene posizionato nella posizione corretta nell'immagine a destra utilizzando un righello personalizzato
come mostrato nell'esempio di codice precedente.
Verificare che i genitori siano vincolati
Per utilizzare in sicurezza WindowInsetsRulers
, assicurati che il genitore 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 dimensioni
nei composable principali.
Allo stesso modo, l'inserimento di un componente componibile che utilizza WindowInsetsRulers
all'interno di un
contenitore scorrevole come verticalScroll
può causare un comportamento imprevisto, in quanto
il contenitore scorrevole fornisce vincoli di altezza illimitati, che sono
incompatibili con la logica del righello.