WindowInsets
to standardowy interfejs API w Jetpack Compose do obsługi obszarów ekranu, które są częściowo lub całkowicie zasłonięte przez interfejs systemu. Obejmują one pasek stanu, pasek nawigacji i klawiaturę ekranową. Możesz też przekazać predefiniowane wartości WindowInsetsRulers
, takie jak SafeDrawing
do Modifier.fitInside
lub Modifier.fitOutside
, aby dopasować treść do pasków systemowych i wycięcia na wyświetlaczu, lub utworzyć niestandardowe wartości WindowInsetsRulers
.
Zalety WindowInsetsRulers
- Unika złożoności związanej z wykorzystaniem: działa w fazie umieszczania układu. Oznacza to, że całkowicie pomija łańcuch konsumpcji wstawki i zawsze może podać prawidłowe, bezwzględne pozycje pasków systemowych i wycięć wyświetlacza, niezależnie od tego, co zrobiły układy nadrzędne. Metody
Modifier.fitInside
iModifier.fitOutside
pomagają rozwiązywać problemy, gdy elementy kompozycyjne nadrzędne nieprawidłowo wykorzystują wcięcia. - Łatwe unikanie pasków systemowych: pomaga uniknąć pasków systemowych i wycięcia na wyświetlaczu, a może być prostsze niż bezpośrednie używanie
WindowInsets
. - Duże możliwości dostosowywania: deweloperzy mogą dopasowywać treści do niestandardowych linijek i precyzyjnie kontrolować układy za pomocą układów niestandardowych.
Wady WindowInsetsRulers
- Nie można używać do pomiarów: ponieważ działa w fazie umieszczania, informacje o pozycji, które dostarcza, są niedostępne w poprzedniej fazie pomiaru.
Dopasowywanie treści do metod modyfikatora
Modifier.fitInside
umożliwia aplikacjom dopasowywanie treści do pasków systemowych i wyświetlanie wycięć. Można go używać zamiast WindowInsets
. Modifier.fitOutside
jest zwykle odwrotnością Modifier.fitInside
.
Aby na przykład sprawdzić, czy treść aplikacji nie zasłania pasków systemowych i wycięcia na wyświetlaczu, możesz użyć fitInside(WindowInsetsRulers.safeDrawing.current)
.
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
Poniższa tabela pokazuje, jak wyglądałaby zawartość aplikacji z wstępnie zdefiniowanymi linijkami z wartościami Modifier.fitInside
lub Modifier.fitOutside
.
Wstępnie zdefiniowany typ linijki | ||
---|---|---|
![]() |
![]() |
|
![]() |
Nie dotyczy |
|
![]() |
![]() |
|
![]() |
Nie dotyczy (użyj |
|
![]() |
![]() |
Użycie funkcji Modifier.fitInside
i Modifier.fitOutside
wymaga ograniczenia funkcji kompozycyjnych. Oznacza to, że musisz zdefiniować modyfikatory, takie jak
Modifier.size
lub Modifier.fillMaxSize
.
Niektóre reguły, np. Modifier.fitOutside
na SafeDrawing
i SystemBars
, zwracają wiele reguł. W takim przypadku Android umieszcza element kompozycyjny, używając jednego z tych wymiarów: od lewej, od góry, od prawej lub od dołu.
Unikanie IME za pomocą Modifier.fitInside
Aby obsługiwać elementy dolne za pomocą edytora IME z Modifier.fitInside
, przekaż RectRuler
, który przyjmuje wewnętrzną wartość NavigationBar
i 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() ) } }
Unikanie paska stanu i paska tytułu za pomocą Modifier.fitInside
Podobnie, aby zweryfikować elementy u góry, unikaj paska stanu i paska tytułu wraz z parametrem Modifier.fitInsider
. Przekaż parametr RectRuler
, który przyjmuje wewnętrzną wartość StatusBars
i CaptionBar
.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
Tworzenie niestandardowego celu WindowInsetsRulers
Możesz wyrównać treści do niestandardowych linijek. Rozważmy na przykład przypadek, w którym funkcja kompozycyjna nadrzędna nieprawidłowo obsługuje wstawki, co powoduje problemy z dopełnieniem w funkcji kompozycyjnej podrzędnej. Ten problem można rozwiązać na inne sposoby, np. za pomocą Modifier.fitInside
. Możesz też utworzyć niestandardową linijkę, aby precyzyjnie wyrównać element kompozycyjny podrzędny bez konieczności rozwiązywania problemu w elemencie nadrzędnym, jak pokazano w tym przykładzie i filmie:
@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) } } } }
Poniższy film pokazuje przykład problematycznego wykorzystania wstawki IME spowodowanego przez element nadrzędny w obrazie po lewej stronie oraz użycie niestandardowych linijek w celu rozwiązania problemu po prawej stronie. Pod elementem TextField
Composable widać dodatkowe dopełnienie, ponieważ dopełnienie paska nawigacyjnego nie zostało wykorzystane przez element nadrzędny. Element podrzędny jest umieszczany we właściwym miejscu na prawym obrazie za pomocą niestandardowej linijki, jak widać w przykładowym kodzie powyżej.
Sprawdzanie, czy rodzice mają ograniczenia
Aby bezpiecznie korzystać z WindowInsetsRulers
, rodzic musi podać prawidłowe ograniczenia. Elementy nadrzędne muszą mieć określony rozmiar i nie mogą zależeć od rozmiaru elementu podrzędnego, który używa WindowInsetsRulers
. Użyj właściwości fillMaxSize
lub innych modyfikatorów rozmiaru w komponentach nadrzędnych.
Podobnie umieszczenie komponentu kompozycyjnego, który używa WindowInsetsRulers
, w kontenerze przewijanym, takim jak verticalScroll
, może powodować nieoczekiwane działanie, ponieważ kontener przewijany zapewnia nieograniczone ograniczenia wysokości, które są niezgodne z logiką linijki.