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 nawigacyjny i klawiaturę ekranową. Możesz też przekazać wstępnie zdefiniowane WindowInsetsRulers, takie jak SafeDrawing, do Modifier.fitInside lub Modifier.fitOutside, aby dopasować treści do pasków systemowych i wycięcia w ekranie, lub utworzyć niestandardowe WindowInsetsRulers.
Zalety WindowInsetsRulers
- Unika złożoności wykorzystania: działa podczas fazy rozmieszczania układu. Oznacza to, że całkowicie pomija łańcuch wykorzystania 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. Metody
Modifier.fitInsideiModifier.fitOutsidesą przydatne do rozwiązywania problemów, gdy elementy kompozycyjne nadrzędne nieprawidłowo wykorzystują wstawki. - Łatwe unikanie pasków systemu: pomaga uniknąć nakładania się treści aplikacji na paski systemu i wycięcie w ekranie. 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 dzięki niestandardowym układom.
Wady: WindowInsetsRulers
- Nie można używać do pomiaru: ponieważ działa podczas fazy umieszczania, informacje o pozycji, które dostarcza, nie są dostępne podczas wcześniejszej fazy pomiaru.
Wyrównywanie treści za pomocą metod modyfikatora
Modifier.fitInside umożliwia aplikacjom dopasowywanie treści do pasków systemowych i wycięć w 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 nachodzą na paski systemowe i wycięcie wyświetlacza, 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 pokazujemy, jak wyglądałaby zawartość aplikacji ze wstępnie zdefiniowanymi linijkami z Modifier.fitInside lub Modifier.fitOutside.
| Wstępnie zdefiniowany typ reguły | ||
|---|---|---|
![]() |
![]() |
|
![]() |
Nie dotyczy |
|
![]() |
![]() |
|
![]() |
Nie dotyczy (użyj |
|
![]() |
![]() |
Używanie 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 linijki, takie jak Modifier.fitOutside w SafeDrawing i SystemBars, zwracają wiele linijek. W takim przypadku Android umieszcza element kompozycyjny, używając jednej linijki od lewej, góry, prawej i dołu.
Unikanie IME za pomocą Modifier.fitInside
Aby obsłużyć elementy dolne 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 podpisów za pomocą Modifier.fitInside
Podobnie, aby sprawdzić, czy elementy u góry nie nachodzą na pasek stanu i pasek podpisu, razem z Modifier.fitInside 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 ) ) ) }
Utwórz niestandardowy cel WindowInsetsRulers
Możesz wyrównywać treści do niestandardowych linijek. Rozważmy na przykład przypadek użycia, w którym nadrzędna funkcja kompozycyjna 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, m.in. 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 wykorzystania wstawki IME spowodowanego przez nadrzędny element nadrzędny na obrazie po lewej stronie oraz użycie niestandardowych linijek do rozwiązania problemu po prawej stronie. Pod elementem kompozycyjnym TextField wyświetlane jest dodatkowe wypełnienie, ponieważ wypełnienie paska nawigacyjnego nie zostało wykorzystane przez element nadrzędny. Na obrazie po prawej stronie element podrzędny jest umieszczony we właściwym miejscu za pomocą niestandardowej linijki, jak widać w przykładowym kodzie powyżej.
Sprawdzanie, czy elementy nadrzędne są ograniczone
Aby bezpiecznie używać WindowInsetsRulers, upewnij się, że element nadrzędny zawiera 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 fillMaxSize lub innych modyfikatorów rozmiaru w komponentach nadrzędnych.
Podobnie umieszczenie elementu kompozycyjnego, który używa WindowInsetsRulers, w kontenerze przewijania, takim jak verticalScroll, może spowodować nieoczekiwane działanie, ponieważ kontener przewijania zapewnia nieograniczone ograniczenia wysokości, które są niezgodne z logiką linijki.







