Konfigurowanie wstawek okien

Gdy aktywność przejmie kontrolę nad obsługą wszystkich elementów wstawianych, 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 wcię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 od krawędzi do krawędzi. 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, które zostały przeniesione 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 początkową stronę elementu WindowInsets jako szerokość (np. Modifier.width).

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

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

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

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

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

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

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

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

Zużycie w przypadku wstawki

Modyfikatory dopełnienia wewnętrznego (windowInsetsPadding i pomocnicze, np. safeDrawingPadding) automatycznie wykorzystują część wstawek, 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 wykorzystują 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 pasków systemowych:

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

Gdy IME jest zamknięty, modyfikator imePadding() nie stosuje dopełnienia, ponieważ IME nie ma wysokości. Modyfikator imePadding() nie stosuje dopełnienia, więc nie są używane żadne wcięcia, a wysokość elementu Spacer będzie równa rozmiarowi dolnej krawędzi paska systemowego.

Gdy otworzy się edytor IME, wstawki IME zostaną animowane, aby dopasować się do jego rozmiaru, a modyfikator imePadding() zacznie stosować dolne dopełnienie, 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. Wysokość Spacer zaczyna się więc zmniejszać, ponieważ część odstępu dla pasków systemowych została już zastosowana przez modyfikator imePadding(). Gdy modyfikator imePadding() stosuje dopełnienie u dołu większe niż paski systemowe, wysokość elementu Spacer wynosi zero.

Gdy IME się zamyka, zmiany zachodzą w odwrotnej kolejności: element Spacer zaczyna się rozszerzać od wysokości zera, gdy element imePadding() jest mniejszy niż dolna krawędź paska systemowego, aż w końcu element Spacer osiąga wysokość dolnej krawędzi paska systemowego, gdy IME jest całkowicie animowany.

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

Dzieje się tak dzięki komunikacji między wszystkimi modyfikatoramiwindowInsetsPadding. Można na to wpłynąć na kilka innych sposobów.

Modifier.consumeWindowInsets(insets: WindowInsets) też zużywa wcięcia w taki sam sposób jak Modifier.windowInsetsPadding, ale nie stosuje zużytych wcięć 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łe 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 nieprzetworzonych 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 wcięć, które korzystają z podstawowych interfejsów API platformy zarządzających wcięciami. Ze względu na to zachowanie platformy wstawki mają specjalną relację z fazami Jetpack Compose.

Wartości wstawek są aktualizowane po fazie kompozycji, ale przed fazą układu. Oznacza to, że odczytywanie wartości wstawek w kompozycji zwykle używa wartości wstawek z opóźnieniem 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.