Konfigurowanie wstawek okien

Aby zezwolić aplikacji na pełną kontrolę nad miejscem wyświetlania treści, wykonaj te czynności konfiguracyjne. Jeśli tego nie zrobisz, aplikacja może rysować czarne lub jednolite kolory za interfejsem systemu albo nie animować synchronicznie z klawiaturą ekranową.

  1. Kieruj aplikację na Androida 15 (API na poziomie 35) lub nowszego, aby wymusić wyświetlanie od krawędzi do krawędzi na Androidzie 15 i nowszym. Aplikacja wyświetla się za interfejsem systemu. Możesz dostosować interfejs aplikacji, obsługując wcięcia.
  2. Opcjonalnie możesz wywołać enableEdgeToEdge()Activity.onCreate(), co umożliwi wyświetlanie aplikacji bez ramki w poprzednich wersjach Androida.
  3. Ustaw android:windowSoftInputMode="adjustResize" w polu AktywnośćAndroidManifest.xml. To ustawienie umożliwia aplikacji otrzymywanie rozmiaru programowego edytora IME jako wstawień, co pomaga zastosować odpowiedni układ i wypełnienie, gdy edytor IME pojawia się i znika w aplikacji.

    <!-- In your AndroidManifest.xml file: -->
    <activity
      android:name=".ui.MainActivity"
      android:label="@string/app_name"
      android:windowSoftInputMode="adjustResize"
      android:theme="@style/Theme.MyApplication"
      android:exported="true">
    

Używanie interfejsów API Compose

Gdy aktywność przejmie kontrolę nad obsługą wszystkich elementów wstawianych, możesz użyć interfejsów API Compose, aby mieć pewność, że 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.

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 przeniesionych do API 21. W konsekwencji wszystkie układy korzystające z tych wcięć są automatycznie animowane w miarę zmiany wartości wcięć.

Istnieją 2 główne sposoby używania tych typów wstawek do dostosowywania układów Composable: modyfikatory dopełnienia i modyfikatory rozmiaru wstawki.

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 funkcji Modifier.windowInsetsPadding(WindowInsets.safeDrawing). Istnieją analogiczne modyfikatory dla innych typów wstawień.

Modyfikatory rozmiaru wstawki

Te modyfikatory stosują ilość wstawień okna, ustawiając rozmiar komponentu na rozmiar wstawień:

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ą 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 w przestrzeni 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, takie jak 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. Ponieważ modyfikator imePadding() nie stosuje żadnego dopełnienia, nie są używane żadne wcięcia, a wysokość elementu Spacer będzie równa rozmiarowi dolnej części paska systemowego.

Gdy otworzy się edytor IME, wstawki IME zostaną animowane, aby dopasować się do jego rozmiaru, a modyfikator imePadding() zacznie stosować do imePadding() dopełnienie u dołu, aby zmienić jego rozmiar podczas otwierania edytora IME.LazyColumn 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 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ągnie wysokość dolnej krawędzi paska systemowego, gdy IME całkowicie zniknie.

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

Działanie to jest realizowane dzięki komunikacji między wszystkimi modyfikatorami windowInsetsPadding i może być modyfikowane na kilka innych sposobów.

Modifier.consumeWindowInsets(insets: WindowInsets) zużywa też wstawki w taki sam sposób jak Modifier.windowInsetsPadding, ale nie stosuje zużytych 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ł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 surowych wartości wstawień okien 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 i rozmiaru wstawek okien.

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 wcięcia 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, 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.