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 nawigacyjny 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 WindowInsetsRulers.
Zalety WindowInsetsRulers
- Unika złożoności związanej z konsumpcją: działa w fazie umieszczania układu. Oznacza to, że całkowicie pomija łańcuch konsumpcji wstawki i zawsze może podawać prawidłowe, bezwzględne pozycje pasków systemowych i wycięć wyświetlacza, niezależnie od tego, co zrobiły układy nadrzędne. Korzystanie z metod
Modifier.fitInsidelubModifier.fitOutsidejest przydatne w rozwiązywaniu problemów, gdy elementy kompozycyjne nadrzędne nieprawidłowo wykorzystują wstawki. - Łatwe unikanie pasków systemu: pomaga uniknąć pasków systemu 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, dostarczane przez niego informacje o pozycji są niedostępne w poprzedniej fazie pomiaru.
Dopasowywanie treści do metod modyfikatora
Modifier.fitInside umożliwia aplikacjom wyrównywanie treści do pasków systemowych i wyświetlanie wycięć. Możesz go użyć zamiast WindowInsets. Modifier.fitOutside jest zwykle odwrotnością Modifier.fitInside.
Aby na przykład sprawdzić, czy zawartość 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 (zamiast niej użyj zasad |
|
![]() |
![]() |
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 u dołu za pomocą edytora IME z Modifier.fitInside, przekaż RectRuler, który przyjmuje najbardziej 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 sprawdzić elementy u góry, unikaj paska stanu i paska tytułu razem z Modifier.fitInsider. Przekaż RectRuler, które 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 ) ) ) }
Utwórz niestandardową 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 podrzędnej funkcji kompozycyjnej. 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ć dodatkowy odstęp, ponieważ odstęp paska nawigacyjnego nie został wykorzystany przez element nadrzędny. Element podrzędny jest umieszczany we właściwym miejscu na prawym obrazie za pomocą niestandardowej linijki, jak 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żywaj właściwości fillMaxSize lub innych modyfikatorów rozmiaru
w przypadku komponentów 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.







