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. Te obszary obejmują pasek stanu, pasek nawigacji i klawiaturę ekranową. Możesz
też przekazać wstępnie zdefiniowane WindowInsetsRulers, takie jak
SafeDrawing, do Modifier.fitInside lub Modifier.fitOutside
, aby wyrównać treści z paskami systemu i wycięciem w ekranie, albo utworzyć
niestandardowe WindowInsetsRulers.
Zalety WindowInsetsRulers
- Unikanie złożoności zużycia: działa w fazie umieszczania
układu. Oznacza to, że całkowicie pomija łańcuch zużycia wstawki i zawsze może podać prawidłowe, bezwzględne położenie pasków systemu i wycięć na ekranie, niezależnie od tego, co zrobiły układy nadrzędne. Używanie metod
Modifier.fitInsidelubModifier.fitOutsidepomaga rozwiązywać problemy, gdy elementy kompozycyjne przodków nieprawidłowo zużywają wstawki. - Łatwe unikanie pasków systemu: pomaga treściom aplikacji unikać pasków systemu
i wycięcia w ekranie, a także może być prostsze niż bezpośrednie używanie
WindowInsets. - Duże możliwości dostosowania: deweloperzy mogą wyrównywać treści do niestandardowych linijek i precyzyjnie kontrolować układy za pomocą układów niestandardowych.
Wady WindowInsetsRulers
- Nie można używać do pomiaru: ponieważ działa w fazie umieszczania , informacje o położeniu, które podaje, są niedostępne w wcześniejszej fazie pomiaru.
Wyrównywanie treści za pomocą metod modyfikatora
Modifier.fitInside umożliwia aplikacjom wyrównywanie treści do pasków systemu i wycięć na ekranie. Można go używać zamiast WindowInsets.
Modifier.fitOutside jest zwykle odwrotnością Modifier.fitInside.
Aby na przykład sprawdzić, czy treści aplikacji nie zasłaniają pasków systemu i wycięcia na ekranie, 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) ) }
W tabeli poniżej pokazano, jak wyglądałyby treści aplikacji w przypadku wstępnie zdefiniowanych linijek z Modifier.fitInside lub Modifier.fitOutside.
| Typ wstępnie zdefiniowanej linijki | ||
|---|---|---|
![]() |
![]() |
|
![]() |
Nie dotyczy |
|
![]() |
![]() |
|
![]() |
Nie dotyczy (użyj zamiast tego |
|
![]() |
![]() |
Używanie Modifier.fitInside i Modifier.fitOutside wymaga, aby elementy kompozycyjne były ograniczone. Oznacza to, że musisz zdefiniować modyfikatory, takie jak Modifier.size lub Modifier.fillMaxSize.
Niektóre linijki, takie jak Modifier.fitOutside w przypadku SafeDrawing i SystemBars, zwracają wiele linijek. W takim przypadku Android umieszcza element kompozycyjny za pomocą jednej linijki z lewej, górnej, prawej lub dolnej strony.
Unikanie IME za pomocą Modifier.fitInside
Aby obsługiwać elementy dolne za pomocą 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 podpisów za pomocą Modifier.fitInside
Podobnie, aby sprawdzić, czy elementy górne nie zasłaniają paska stanu i paska podpisów razem z Modifier.fitInsider, przekaż RectRuler, który przyjmuje najbardziej 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 niestandardowych WindowInsetsRulers
Możesz wyrównywać treści do niestandardowych linijek. Rozważ na przykład przypadek użycia, w którym element kompozycyjny nadrzędny nieprawidłowo obsługuje wstawki, co powoduje problemy z dopełnieniem w elemencie podrzędnym. Ten problem można rozwiązać na inne sposoby, np. za pomocą Modifier.fitInside, ale 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 zużycia wstawki IME spowodowanego przez element nadrzędny w obrazie po lewej stronie oraz użycie niestandardowych linijek do rozwiązania problemu po prawej stronie. Pod elementem kompozycyjnym TextField widoczne jest dodatkowe dopełnienie, ponieważ dopełnienie paska nawigacji nie zostało zużyte przez element nadrzędny. Element podrzędny jest umieszczony w prawidłowym miejscu na obrazie po prawej stronie za pomocą niestandardowej linijki, jak widać w poprzednim przykładzie kodu.
Sprawdzanie, czy elementy nadrzędne są ograniczone
Aby bezpiecznie używać WindowInsetsRulers, upewnij się, że element nadrzędny zapewnia prawidłowe ograniczenia. Elementy nadrzędne muszą mieć zdefiniowany rozmiar i nie mogą zależeć od rozmiaru elementu podrzędnego, który używa WindowInsetsRulers. Użyj fillMaxSize lub innych modyfikatorów rozmiaru w elementach kompozycyjnych nadrzędnych.
Podobnie umieszczenie elementu 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.







