Konfigurowanie wstawek okien

Aby umożliwić aplikacji pełną kontrolę nad tym, gdzie może rysować treści, wykonaj te czynności konfiguracyjne. Bez wykonania tych czynności aplikacja może wyświetlać czarny kolor lub jednolite kolory za interfejsem systemu albo nie animować się synchronicznie z klawiaturą programową.

  1. Kieruj aplikację na Androida 15 (poziom API 35) lub nowszego, aby wymusić pełnowymiarowy interfejs na Androidzie 15 i nowszych. Aplikacja wyświetla się za interfejsem użytkownika systemu. Możesz dostosować interfejs aplikacji, obsługując wstawienia w ramkach.
  2. Opcjonalnie możesz wywołać metodę enableEdgeToEdge()Activity.onCreate(), aby umożliwić wyświetlanie aplikacji bez ramki w poprzednich wersjach Androida.
  3. Ustaw wartość android:windowSoftInputMode="adjustResize" w polu AndroidManifest.xml w sekcji Aktywność. To ustawienie pozwala aplikacji otrzymywać rozmiar oprogramowania IME jako wstawki, co ułatwia zastosowanie odpowiedniego układu i marginesu podczas pojawiania się i znikania oprogramowania IME 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">
    

Korzystanie z interfejsów Compose API

Gdy Twoja aktywność przejmie kontrolę nad obsługą wszystkich wstawień, możesz użyć interfejsów API Compose, aby upewnić się, że treści nie są zasłonięte, a elementy, z którymi można wchodzić w interakcje, nie nakładają się na interfejs użytkownika systemu. Te interfejsy API synchronizują też układ aplikacji z zmianami w insetach.

Oto najprostsza metoda zastosowania wstawek 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 wstawki okna safeDrawing jako wypełnienie wokół całej zawartości aplikacji. Dzięki temu elementy, z którymi można wchodzić w interakcję, nie będą nakładać się na interfejs systemu, ale oznacza to też, że żadna część aplikacji nie będzie narysowana za interfejsem systemu, aby uzyskać efekt obrazu sięgającego krawędzi. Aby w pełni wykorzystać cały ekran, musisz precyzyjnie określić, gdzie wstawiane są wstawki. Możesz to zrobić w przypadku każdego ekranu lub każdego komponentu.

Wszystkie te typy wstawek są animowane automatycznie za pomocą animacji IME przeniesionych do interfejsu API 21. W związku z tym wszystkie układy korzystające z tych wstawek są automatycznie animowane wraz ze zmianą wartości wstawek.

Istnieją 2 podstawowe sposoby korzystania z tych typów wstawek do dostosowywania układów kompozytowych: modyfikatory wypełnień i modyfikatory rozmiaru wstawki.

Modyfikatory wypełniania

Modifier.windowInsetsPadding(windowInsets: WindowInsets) stosuje podane zaokrąglenia okna jako wypełnienie, działając tak samo jak Modifier.padding. Na przykład Modifier.windowInsetsPadding(WindowInsets.safeDrawing) stosuje bezpieczne wstawione rysunki jako wypełnienie po wszystkich 4 stronach.

Dostępnych jest też kilka wbudowanych metod pomocniczych dla najczęściej używanych typów wstawek. Modifier.safeDrawingPadding() to jedna z takich metod, równoważna funkcji Modifier.windowInsetsPadding(WindowInsets.safeDrawing). Istnieją analogiczne modyfikatory dla innych typów wstawek.

Modyfikatory rozmiaru wnęki

Te modyfikatory określają wielkość wstawionych okien, ustawiając rozmiar komponentu na rozmiar wstawionych okien:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

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

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

Stosuje końcową stronę zaokrąglenia okna jako szerokość (np. Modifier.width).

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

Stosuje górną stronę zawijania okna jako wysokość (jak Modifier.height).

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

Dolny bok windowInsets jest stosowany jako wysokość (np. Modifier.height).

Te modyfikatory są szczególnie przydatne do ustawiania rozmiaru Spacer, który zajmuje miejsce w ramkach wstawionych:

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

Konsumpcja w ramce

Modyfikatory wkładki (windowInsetsPadding i pomocnicze, takie jak safeDrawingPadding) automatycznie wykorzystują część wkładki, która jest stosowana jako wypełnienie. Wchodząc głębiej w drzewo kompozycji, wiesz, że wpisane modyfikatory wypełniania w ramkach i modyfikatory rozmiaru w ramkach, a także modyfikatory rozmiaru w ramkach zewnętrznych, wykorzystują już część wstawek. Unikaj używania tej samej części wstawek więcej niż raz, ponieważ spowodowałoby to zbyt dużo dodatkowej przestrzeni.

Zmienne rozmiaru wstawek również zapobiegają wielokrotnemu używaniu tej samej części wstawek, jeśli zostały one już wykorzystane. Ponieważ jednak zmieniają one bezpośrednio swój rozmiar, nie wykorzystują one samych wstawek.

W efekcie modyfikatory wypełnienia zagnieżdżonego automatycznie zmieniają ilość wypełnienia zastosowaną do każdego komponentu.

W tym samym przykładzie LazyColumn rozmiar obiektu LazyColumn jest zmieniany przez modyfikator imePadding. W elementach LazyColumn ostatni element ma wysokość odpowiadającą wysokości dolnej krawędzi pasków systemu:

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

Gdy IME jest zamknięte, modyfikator imePadding() nie stosuje wypełnienia, ponieważ IME nie ma wysokości. Ponieważ modyfikator imePadding() nie stosuje żadnych wypełnień, nie są używane żadne wstawki, a wysokość elementu Spacer będzie odpowiadać rozmiarowi dolnej strony pasków systemu.

Gdy otworzy się klawiatura, jej wstawki animują się, aby dopasować się do jej rozmiaru, a modyfikator imePadding() zacznie stosować wypełnienie dolne, aby zmienić rozmiar LazyColumn w miarę otwierania klawiatury. Gdy modyfikator imePadding() zacznie stosować wypełnienie dolne, zacznie też zużywać tę liczbę wstawek. W związku z tym wysokość Spacer zaczyna się zmniejszać, ponieważ część odstępów między elementami systemu została już zastosowana przez modyfikator imePadding(). Gdy modyfikator imePadding() zastosuje dopełnienie dolne większe niż paski systemowe, wysokość Spacer wynosi 0.

Gdy IME się zamyka, zmiany zachodzą w odwrotnej kolejności: gdy Spacer jest mniejsza niż dolna krawędź pasków systemu, Spacer zaczyna się rozszerzać od wysokości 0, aż w końcu osiągnie wysokość odpowiadającą dolnej krawędzi pasków systemu, gdy IME zostanie całkowicie zamknięte.imePadding()

Rysunek 2. Kolumna z automatycznym wypełnianiem od krawędzi do krawędzi z wartością TextField.

To zachowanie jest realizowane przez komunikację między wszystkimi modyfikatorami windowInsetsPadding i może być modyfikowane na kilka sposobów.

Modifier.consumeWindowInsets(insets: WindowInsets) również wykorzystuje wstawione elementy w taki sam sposób jak Modifier.windowInsetsPadding, ale nie stosuje wstawionych elementów jako wypełnienia. Jest to przydatne w połączeniu z modyfikatorami rozmiaru wgłębienia, aby wskazać elementom nadrzędnym, że pewna liczba wgłębień 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))
}

Modifier.consumeWindowInsets(paddingValues: PaddingValues) działa bardzo podobnie do wersji z argumentem WindowInsets, ale przyjmuje dowolną wartość PaddingValues. Jest to przydatne, gdy chcesz poinformować dzieci, że wypełnienie lub odstępy są zapewnione przez inny mechanizm niż modyfikatory wbudowanego wypełniania, takie jak zwykłe Modifier.padding lub odstępy o stałej wysokości:

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

W przypadku, gdy potrzebne są nieprzetworzone wstawki okna, użyj bezpośrednio wartości WindowInsets lub polecenia WindowInsets.asPaddingValues(), aby zwrócić PaddingValues wstawek, które nie są objęte przetwarzaniem. Jednak ze względu na te ograniczenia zalecamy, aby w miarę możliwości używać modyfikatorów wypełniania okna i modyfikatorów rozmiaru okna.

Ramki i fazy Jetpack Compose

Compose używa podstawowych interfejsów API AndroidX do aktualizowania i animowania wgłębień, które korzystają z podstawowych interfejsów API platformy do zarządzania wgłębieniami. Ze względu na to zachowanie platformy wstawki mają szczególny związek z etazami Jetpacka Compose.

Wartości wstawek są aktualizowane po fazie tworzenia kompozycji, ale przed fazą układu. Oznacza to, że odczyt wartości wstawek w kompozycji wykorzystuje zazwyczaj wartość wstawek, która jest o 1 klatka późniejsza. Wbudowane modyfikatory opisane na tej stronie są zaprojektowane tak, aby opóźniać używanie wartości w ramkach do fazy układu. Dzięki temu wartości w ramkach są używane w tym samym ujęciu, w którym są aktualizowane.