Konfigurowanie wstawek okien

Gdy aktywność przejmie kontrolę nad obsługą wszystkich wstawek, możesz użyć interfejsów API Compose, aby sprawdzić, czy treść nie jest zasłonięta, a elementy interaktywne nie nakładają się na interfejs systemu. Te interfejsy API synchronizują też układ aplikacji ze zmianami w marginesach.

Obsługa wcięć za pomocą dopełnienia lub modyfikatorów rozmiaru

Oto na przykład najprostsza metoda zastosowania wcięć do treści całej aplikacji:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

Ten fragment kodu stosuje odcięcia okna safeDrawing jako dopełnienie wokół całej zawartości aplikacji. Zapewnia to, że elementy interaktywne nie będą nakładać się na interfejs systemu, ale oznacza też, że żadna część aplikacji nie będzie rysowana za interfejsem systemu, aby uzyskać efekt bez ramek. Aby w pełni wykorzystać całe okno, musisz precyzyjnie dostosować miejsca, w których mają być stosowane wcięcia, na poziomie poszczególnych ekranów lub komponentów.

Wszystkie te typy wstawek są animowane automatycznie za pomocą animacji IME przeniesionych do API 21. W konsekwencji wszystkie układy korzystające z tych wcięć są automatycznie animowane w miarę zmiany wartości wcięć.

Aby dostosować układy funkcji kompozycyjnych, możesz użyć 3 sposobów obsługi wstawek:

Modyfikatory dopełnienia

Modifier.windowInsetsPadding(windowInsets: WindowInsets) stosuje podane wcięcia okna jako dopełnienie, działając tak samo jak Modifier.padding. Na przykład Modifier.windowInsetsPadding(WindowInsets.safeDrawing) stosuje bezpieczne wstawki rysunkowe jako dopełnienie po wszystkich 4 stronach.

Dostępnych jest też kilka wbudowanych metod narzędziowych dla najpopularniejszych typów wcięć. Modifier.safeDrawingPadding() to jedna z takich metod, która jest odpowiednikiem Modifier.windowInsetsPadding(WindowInsets.safeDrawing). Istnieją analogiczne modyfikatory dla innych typów wcięć.

Modyfikatory rozmiaru wstawki

Te modyfikatory stosują ilość odcięć okna, ustawiając rozmiar komponentu na rozmiar odcięć:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

Stosuje stronę początkową windowInsets jako szerokość (np. Modifier.width).

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

Stosuje szerokość równą końcowej stronie elementu WindowInsets (np. Modifier.width).

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

Stosuje górną część windowInsets jako wysokość (np. Modifier.height).

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

Stosuje dolną część elementu WindowInsets jako wysokość (np. Modifier.height).

Te modyfikatory są szczególnie przydatne do określania rozmiaru elementu Spacer, który zajmuje miejsce wstawień:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Konsumpcja w ramce

Modyfikatory dopełnienia wewnętrznego (windowInsetsPadding i pomocnicze, np. safeDrawingPadding) automatycznie wykorzystują część wcięć, które są stosowane jako dopełnienie. Podczas zagłębiania się w drzewo kompozycji zagnieżdżone modyfikatory dopełnienia wstawki i modyfikatory rozmiaru wstawki wiedzą, że część wstawek została już wykorzystana przez zewnętrzne modyfikatory dopełnienia wstawki, i unikają używania tej samej części wstawek więcej niż raz, co spowodowałoby zbyt dużo dodatkowego miejsca.

Modyfikatory rozmiaru wstawki również unikają używania tej samej części wstawek więcej niż raz, jeśli wstawki zostały już wykorzystane. Ponieważ jednak zmieniają one swój rozmiar bezpośrednio, nie zużywają samych wstawek.

W rezultacie zagnieżdżone modyfikatory dopełnienia automatycznie zmieniają ilość dopełnienia zastosowanego do każdego komponentu.

Patrząc na ten sam LazyColumn przykład co wcześniej, widzimy, że LazyColumn jest zmieniany przez modyfikator imePadding. W sekcji LazyColumn ostatni element ma wysokość dolnej części paska systemowego:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

Gdy IME jest zamknięty, imePadding() nie stosuje dopełnienia. W związku z tym nie są używane żadne wcięcia, a wysokość Spacer jest równa wysokości dolnych pasków systemowych.

Gdy otworzy się edytor IME, wstawki IME zostaną animowane, aby dopasować się do jego rozmiaru, a modyfikator imePadding() zacznie stosować dolny odstęp, aby zmienić rozmiar LazyColumn podczas otwierania edytora IME. Gdy modyfikator imePadding() zacznie stosować dopełnienie u dołu, zacznie też zużywać tę ilość wstawek. Dlatego wysokość Spacer zaczyna się zmniejszać, ponieważ część odstępu między paskami systemowymi została już zastosowana przez modyfikator imePadding(). Gdy modyfikator imePadding() stosuje dolne dopełnienie o wartości większej niż paski systemowe, wysokość elementu Spacer wynosi zero.

Gdy IME zostanie zamknięty, zmiany zostaną cofnięte: Spacer rozszerzy się z wysokości zerowej, ponieważ imePadding() będzie stosować mniejszą wartość niż dolne paski systemowe. Gdy IME całkowicie zniknie, wysokość Spacer będzie zgodna z wysokością pasków systemowych.

Rysunek 2. Kolumna leniwa od krawędzi do krawędzi z TextField.

Jest to możliwe dzięki komunikacji między wszystkimi modyfikatorami windowInsetsPadding. Można na to wpływać na kilka innych sposobów.

Modifier.consumeWindowInsets(insets: WindowInsets) też wykorzystuje wstawki w taki sam sposób jak Modifier.windowInsetsPadding, ale nie stosuje wykorzystanych wstawek jako dopełnienia. Jest to przydatne w połączeniu z modyfikatorami rozmiaru wstawki, aby wskazać elementom równorzędnym, że określona liczba wstawek została już wykorzystana:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

Funkcja Modifier.consumeWindowInsets(paddingValues: PaddingValues) działa bardzo podobnie do wersji z argumentem WindowInsets, ale przyjmuje dowolny argument PaddingValues. Jest to przydatne, gdy chcesz poinformować dzieci, że dopełnienie lub odstępy są zapewniane przez inny mechanizm niż modyfikatory dopełnienia wewnętrznego, np. zwykły Modifier.padding lub elementy odstępu o stałej wysokości:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

Jeśli potrzebujesz surowych wartości wstawień okna bez ich wykorzystania, użyj bezpośrednio wartości WindowInsets lub użyj WindowInsets.asPaddingValues(), aby zwrócić PaddingValues wstawień, na które nie ma wpływu wykorzystanie. Ze względu na poniższe zastrzeżenia w miarę możliwości używaj modyfikatorów dopełnienia odcięć okna i modyfikatorów rozmiaru odcięć okna.

Wstawki i fazy Jetpack Compose

Compose używa podstawowych interfejsów API AndroidX do aktualizowania i animowania wstawek, które korzystają z podstawowych interfejsów API platformy zarządzających wstawkami. Ze względu na to zachowanie platformy wcięcia mają specjalną relację z fazami Jetpack Compose.

Wartość wstawek jest aktualizowana po fazie kompozycji, ale przed fazą układu. Oznacza to, że odczytywanie wartości wstawek w kompozycji zwykle wykorzystuje wartość wstawek, która jest opóźniona o 1 klatkę. Wbudowane modyfikatory opisane na tej stronie są zaprojektowane tak, aby opóźniać używanie wartości wstawek do fazy układu, co zapewnia, że wartości wstawek są używane w tej samej ramce, w której są aktualizowane.