Platforma Android odpowiada za rysowanie interfejsu systemu, w tym paska stanu i nawigacji. Interfejs ten wyświetla się niezależnie
od tego, jakiej aplikacji używa użytkownik. WindowInsets
podaje informacje o interfejsie systemu, aby zapewnić, że aplikacja wyświetla się we właściwym obszarze, a interfejs nie jest zasłonięty.
Domyślnie interfejs aplikacji jest ograniczony do interfejsu systemowego, np. paska stanu i nawigacji. Dzięki temu zawartość aplikacji nie jest zasłonięta przez elementy interfejsu systemu.
Zalecamy jednak, aby aplikacje wyświetlały się w tych obszarach, w których wyświetla się też interfejs systemu. Zapewni to większy komfort użytkowników i umożliwi pełne wykorzystanie dostępnej przestrzeni okna aplikacji. Pozwala to też aplikacjom animować się razem z interfejsem systemu, zwłaszcza przy wyświetlaniu i ukrywaniu klawiatury oprogramowania.
Włączenie wyświetlania treści w tych regionach i za pomocą interfejsu systemowego jest nazywane przesyłaniem treści od krawędzi do krawędzi. Na tej stronie poznasz różne typy wstawionych wkładek, dowiesz się, jak zacząć korzystać z wbudowanych wzorów i jak używać wbudowanych interfejsów API do animowania UI i unikania zasłaniania części aplikacji.
Podstawy wstawiania
Gdy aplikacja jest w całości dopracowana, jej ważne treści i interakcje nie powinny być zasłonięte przez interfejs systemu. Jeśli na przykład przycisk znajduje się za paskiem nawigacyjnym, użytkownik może nie być w stanie go kliknąć.
Rozmiar interfejsu systemu i informacje o tym, gdzie się znajduje, są określane za pomocą zestawów.
Każda część interfejsu systemu ma odpowiedni typ wstawienia, który opisuje jej rozmiar i miejsce umieszczenia. Na przykład wcięcia paska stanu określają rozmiar i pozycję paska stanu, a wstawki paska nawigacyjnego – rozmiar i pozycję paska nawigacyjnego. Każdy typ wstawienia składa się z czterech wymiarów pikseli: góra, lewa, prawa i dół. Te wymiary określają, jak daleko interfejs systemu rozciąga się od odpowiednich boków okna aplikacji. Aby uniknąć nakładania się na ten typ interfejsu systemu, interfejs aplikacji musi być wstawiony przez tę wartość.
Te wbudowane typy wkładek na Androida są dostępne w WindowInsets
:
Wstawki opisujące paski stanu. Są to górne paski interfejsu użytkownika, które zawierają ikony powiadomień i inne wskaźniki. |
|
Pasek stanu wbudowuje się, gdy jest widoczny. Jeśli paski stanu są obecnie ukryte (z powodu włączenia pełnego ekranu), wstawki głównego paska stanu będą puste, ale nie będą puste. |
|
Wstawki opisujące paski nawigacyjne. Są to paski interfejsu systemu z lewej, prawej lub u dołu, które opisują pasek aplikacji lub ikony nawigacji. Mogą się one zmieniać w czasie działania w zależności od preferowanej przez użytkownika metody nawigacji oraz interakcji z paskiem aplikacji. |
|
Pasek nawigacyjny jest wstawiane, gdy są widoczne. Jeśli paski nawigacyjne są obecnie ukryte (z powodu włączenia pełnego ekranu), wstawki głównego paska nawigacyjnego będą puste, ale nie będą puste. |
|
Wstawka opisująca dekoracje okna interfejsu systemu w przypadku dowolnego okna, np. górny pasek tytułu. |
|
Pasek napisów jest wstawiane, gdy są widoczne. Jeśli paski napisów są obecnie ukryte, główne wcięcia pasków napisów będą puste, ale te wstawki nie będą puste. |
|
Połączenie wcięć pasków systemowych, które obejmują paski stanu, nawigacji i napisów. |
|
Pasek systemowy jest wstawiane, gdy są widoczne. Jeśli paski systemowe są obecnie ukryte (z powodu włączenia się w tryb pełnego ekranu), główne wcięcia pasków systemowych będą puste, ale nie będą puste. |
|
Wstawki opisujące ilość miejsca na dole zajmowanego przez klawiaturę programową. |
|
Wstawki opisujące ilość miejsca zajmowanego przez klawiaturę programową przed bieżącą animacją klawiatury. |
|
Wstawki opisujące ilość miejsca, jaką klawiatura programowa zajmie po bieżącej animacji klawiatury. |
|
Rodzaj wkładek opisujących bardziej szczegółowe informacje o interfejsie nawigacji, podające ilość miejsca, w którym „dotknięcia” zajmuje system, a nie aplikacja. W przypadku przezroczystych pasków nawigacyjnych z nawigacją przy użyciu gestów niektóre elementy aplikacji można klikać w interfejsie systemowym. |
|
Elementy do kliknięcia pojawiają się, gdy są widoczne. Jeśli elementy do kliknięcia są obecnie ukryte (z powodu przejścia w pojemny tryb pełnoekranowy), główne wstawki z elementami do kliknięcia będą puste, ale nie będą puste. |
|
Wstawki reprezentujące liczbę wektorów, w których system przechwytuje gesty na potrzeby nawigacji. Aplikacje mogą ręcznie określać sposób obsługi ograniczonej liczby tych gestów za pomocą |
|
Zestaw gestów systemowych, które będą zawsze obsługiwane przez system i z których nie można zrezygnować w |
|
Wcięcia reprezentujące odstępy potrzebne do uniknięcia nakładania się na wycięcie w ekranie (wycięcie lub małe otwory w ekranie). |
|
Wgłębienia reprezentujące zakrzywione obszary wodospadu. Wyświetlacz kaskadowy ma zakrzywione obszary wzdłuż krawędzi ekranu w miejscach, w których ekran zaczyna się zawijać wzdłuż boków urządzenia. |
Te typy podsumowujemy za pomocą 3 „bezpiecznych” typów wstawienia, które zapewniają, że treść nie jest zasłonięta:
Te „bezpieczne” typy wstawionych wkładek chronią treści na różne sposoby w zależności od leżących u nich elementów platformy:
- Używaj narzędzia
WindowInsets.safeDrawing
do ochrony treści, które nie powinny być wyświetlane pod żadnym interfejsem systemu. To najczęstsze zastosowanie wstawienia, które pozwala zapobiegać rysowaniu treści zasłoniętych przez interfejs systemu (częściowo lub całkowicie). - Korzystaj z
WindowInsets.safeGestures
, aby chronić treści za pomocą gestów. Dzięki temu gesty systemu nie kolidują z gestami w aplikacji (np. w arkuszach u dołu, w karuzeli czy w grach). - Użyj
WindowInsets.safeContent
jako kombinacji funkcjiWindowInsets.safeDrawing
iWindowInsets.safeGestures
, aby treści nie nakładały się na siebie ani nie nakładały się na gesty.
Konfiguracja wkładek
Aby zapewnić aplikacji pełną kontrolę nad pobieraniem treści, wykonaj te czynności konfiguracyjne. Jeśli nie wykonasz tych czynności, aplikacja może wyświetlać czarne lub jednolite kolory za interfejsem systemu albo nie animować się synchronicznie z klawiaturą oprogramowania.
- Zadzwoń pod numer
enableEdgeToEdge()
w:Activity.onCreate
. W ramach tego wywołania aplikacja wyświetla się za interfejsem systemu. Aplikacja będzie wtedy kontrolować, jak te wstawki są używane do dostosowywania interfejsu użytkownika. Ustaw
android:windowSoftInputMode="adjustResize"
w wpisie o aktywnościAndroidManifest.xml
. To ustawienie umożliwia aplikacji otrzymywanie rozmiaru programowego edytora IME w postaci wkładek, które można wykorzystać do odpowiedniego dopełnienia i rozmieszczenia treści, gdy 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">
Interfejsy API tworzenia wiadomości
Gdy aktywność przejmie kontrolę nad obsługą wszystkich wstawienia, możesz używać interfejsów API tworzenia, 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 wstawionymi.
Jest to na przykład najprostsza metoda stosowania wstawienia 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 okien safeDrawing
jako dopełnienie wokół całej zawartości aplikacji. Dzięki temu elementy interaktywne nie nakładają się na interfejs systemu, ale żadna aplikacja nie będzie się zasłaniać interfejsem systemu, aby uzyskać efekt „od krawędzi do krawędzi”. Aby w pełni wykorzystać całe okno, musisz dostosować miejsca, w których wcięcia są stosowane, osobno na każdym ekranie, czy krok po kroku.
Wszystkie te typy wstawienia reklamy są animowane automatycznie, korzystając z animacji IME przywróconych do interfejsu API 21. Co więcej, wszystkie układy używające tych wstawienia są automatycznie animowane wraz ze zmianą wartości wstawienia.
Istnieją 2 główne sposoby używania tych rodzajów wstawienia do dostosowywania układów kompozycyjnych: modyfikatory dopełnienia i modyfikatory rozmiaru wstawienia.
Modyfikatory dopełnienia
Modifier.windowInsetsPadding(windowInsets: WindowInsets)
stosuje podane wstawki okna jako dopełnienie, działając w sposób taki jak Modifier.padding
.
Na przykład Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
stosuje bezpieczne wstawki do rysowania jako dopełnienie ze wszystkich 4 stron.
Istnieje też kilka wbudowanych metod narzędzia dla najpopularniejszych typów wstawienia.
Modifier.safeDrawingPadding()
jest jedną z takich metod, równoważną z metodą Modifier.windowInsetsPadding(WindowInsets.safeDrawing)
. Istnieją analogiczne modyfikatory
dla innych typów wstawienia.
Modyfikatory rozmiaru wstawionego
Te modyfikatory powodują zastosowanie liczby wstawionych okien przez ustawienie rozmiaru komponentu na wcięcia:
Stosuje stronę początkową elementów windowInsets jako szerokość (taką jak |
|
Stosuje końcową stronę elementów windowInsets jako szerokość (np. |
|
Stosuje górną stronę wstawki okna (np. |
|
|
Stosuje dolną część elementu windowInsets jako wysokość (np. |
Te modyfikatory są szczególnie przydatne do określania rozmiaru elementu Spacer
, który zajmuje miejsce wstawienia:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Wykorzystanie wbudowanej
Wstawione modyfikatory dopełnienia (windowInsetsPadding
i elementy pomocnicze, takie jak safeDrawingPadding
) automatycznie używają części wkładek, które są stosowane jako dopełnienie. Wgląd w drzewo kompozycji zagnieżdżony jest tylko z zagnieżdżonych modyfikatorów dopełnienia i rozmiaru wstawienia, które wiedzą, że niektóre części i rozmiaru insetów zostały już wykorzystane przez zewnętrzne modyfikatory dopełnienia wstawionego. Unikaj więc używania tej samej części wkładek więcej niż raz, bo spowodowałoby to uzyskanie zbyt wielu dodatkowych przestrzeni.
Modyfikatory rozmiaru wstawienia nie używają też tej samej części wstawienia więcej niż raz, jeśli wstawienia zostały już wykorzystane. Nie używają jednak wkładek, ponieważ zmieniają swój rozmiar bezpośrednio.
W efekcie zagnieżdżone modyfikatory dopełnienia automatycznie zmieniają ilość dopełnienia zastosowanego do każdego elementu kompozycyjnego.
W przypadku tego samego przykładu LazyColumn
co poprzednio widać, że rozmiar elementu LazyColumn
jest zmieniany przez modyfikator imePadding
. Rozmiar ostatniego elementu w elemencie LazyColumn
to wysokość dolnych słupków systemowych:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Po zamknięciu edytora IME modyfikator imePadding()
nie stosuje dopełnienia, ponieważ nie ma on wysokości. Modyfikator imePadding()
nie stosuje dopełnienia, więc nie są stosowane żadne wstawki, a wysokość elementu Spacer
będzie taka sama jak rozmiar dolnej krawędzi słupków systemowych.
Po otwarciu edytora IME wstawki są animowane zgodnie z jego rozmiarem, a modyfikator imePadding()
zaczyna stosować dopełnienie u dołu, aby zmienić rozmiar znacznika LazyColumn
po jego otwarciu. Gdy modyfikator imePadding()
zaczyna stosować dopełnienie u dołu, zaczyna też zużywać tę liczbę wkładek. Dlatego wysokość elementu Spacer
zaczyna się zmniejszać, ponieważ część odstępów między słupkami systemowymi została już zastosowana przez modyfikator imePadding()
. Gdy modyfikator imePadding()
zastosuje dopełnienie u dołu większe niż słupki systemowe, wysokość elementu Spacer
będzie wynosić 0.
Po zamknięciu edytora IME zmiany zachodzą odwrotnie: gdy edytor imePadding()
jest mniejszy od dolnej krawędzi pasków systemowych, Spacer
zaczyna się rozwijać od zera, aż w końcu Spacer
będzie się zgadzać z wysokością dolnej krawędzi słupków systemowych, gdy edytor IME zostanie całkowicie animowany.
Dzieje się tak dzięki komunikacji między wszystkimi modyfikatorami windowInsetsPadding
i można na nie wpływać kilkoma innymi sposobami.
Funkcja Modifier.consumeWindowInsets(insets: WindowInsets)
również używa wstawienia w taki sam sposób jak Modifier.windowInsetsPadding
, ale nie stosuje ich jako dopełnienia. Jest to przydatne w połączeniu z modyfikatorami rozmiaru wstawienia, aby zasygnalizować rodzeństwo, że pewna liczba wstawienia 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 korzysta z arbitrażu PaddingValues
. Jest to przydatne, gdy chcesz poinformować dzieci o tym, że dopełnienie lub odstępy są zapewniane przez inny mechanizm niż wstawiane modyfikatory dopełnienia, takie jak zwykłe Modifier.padding
lub odstępy o stałej wysokości:
@OptIn(ExperimentalLayoutApi::class) Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) { // content Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime)) }
W sytuacjach, gdy potrzebne są nieprzetworzone wstawki okienne bez konsumpcji, używaj bezpośrednio wartości WindowInsets
lub funkcji WindowInsets.asPaddingValues()
, aby zwrócić PaddingValues
wektorów, na które nie ma wpływu wykorzystanie.
Ze względu na poniższe zastrzeżenia lepiej w miarę możliwości używaj modyfikatorów dopełnienia wstawienia okien i modyfikatorów rozmiaru wstawienia okien.
Etapy wektorów i Jetpack Compose
Compose używa podstawowych interfejsów API AndroidaX do aktualizowania i animowania wektorów, które korzystają z bazowych interfejsów API platformy do zarządzania wstawieniami. Ze względu na takie działanie platformy zestawy wektorowe mają specjalny związek z fazami Jetpack Compose.
Wartość wstawienia jest aktualizowana po fazie kompozycji, ale przed fazą układu. Oznacza to, że odczyt wartości wstawienia w kompozycji zwykle używa wartości wstawienia, która jest o jedną klatkę opóźniona. Wbudowane modyfikatory opisane na tej stronie są skonstruowane tak, aby opóźniały korzystanie z wartości zestawu do fazy układu, dzięki czemu wartości wstawienia są używane w tej samej klatce, w której są aktualizowane.
Animacje klawiaturowe IME w języku WindowInsets
Możesz zastosować Modifier.imeNestedScroll()
do przewijanego kontenera, aby automatycznie otwierać i zamykać edytor IME podczas przewijania do dołu.
class WindowInsetsExampleActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) setContent { MaterialTheme { MyScreen() } } } } @OptIn(ExperimentalLayoutApi::class) @Composable fun MyScreen() { Box { LazyColumn( modifier = Modifier .fillMaxSize() // fill the entire window .imePadding() // padding for the bottom for the IME .imeNestedScroll(), // scroll IME at the bottom content = { } ) FloatingActionButton( modifier = Modifier .align(Alignment.BottomEnd) .padding(16.dp) // normal 16dp of padding for FABs .navigationBarsPadding() // padding for navigation bar .imePadding(), // padding for when IME appears onClick = { } ) { Icon(imageVector = Icons.Filled.Add, contentDescription = "Add") } } }
Rysunek 1. Animacje IME
Wbudowana obsługa komponentów Material 3
Aby ułatwić sobie korzystanie, wiele wbudowanych uchwytów kompozycyjnych Material 3 (androidx.compose.material3
) dostaje się samodzielnie w zależności od tego, w jaki sposób elementy kompozycyjne są rozmieszczone w aplikacji zgodnie ze specyfikacją Material.
Elementy kompozycyjne obsługi wstawki
Poniżej znajduje się lista komponentów Material Design, które automatycznie obsługują wstawki.
Paski aplikacji
TopAppBar
/SmallTopAppBar
/CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: stosuje górne i poziome boki pasków systemowych, ponieważ jest używane u góry okna.BottomAppBar
: stosuje dolne i poziome boki pasków systemowych jako dopełnienie.
Kontenery treści
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(treść w modalnym panelu nawigacji): do treści stosuje wstawki pionowe i start.ModalBottomSheet
: stosuje dolne wstawki.NavigationBar
: stosuje wcięcia dolne i poziome.NavigationRail
: stosuje wstawki pionowe i początkowe.
Ruszt
Domyślnie Scaffold
udostępnia wektory jako parametr paddingValues
, które można wykorzystać i wykorzystać.
Scaffold
nie stosuje wstawienia do treści. To Ty ponosisz odpowiedzialność.
Aby np. wykorzystać te wektory z parametrem LazyColumn
wewnątrz właściwości Scaffold
:
Scaffold { innerPadding -> // innerPadding contains inset information for you to use and apply LazyColumn( // consume insets as scaffold doesn't do it by default modifier = Modifier.consumeWindowInsets(innerPadding), contentPadding = innerPadding ) { items(count = 100) { Box( Modifier .fillMaxWidth() .height(50.dp) .background(colors[it % colors.size]) ) } } }
Zastąp domyślne wstawki
Możesz zmienić parametr windowInsets
przekazywany do funkcji kompozycyjnej, aby skonfigurować jej działanie. Może to być inny typ wstawienia okna lub wyłączenie go przez przekazanie pustej instancji: WindowInsets(0, 0, 0, 0)
.
Aby na przykład wyłączyć obsługę wstawienia do obiektu LargeTopAppBar
, ustaw dla parametru windowInsets
pustą instancję:
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
Interakcja z wektorami systemowymi widoku danych
Może być konieczne zastąpienie domyślnych wstawionych elementów, gdy ekran zawiera zarówno widoki, jak i kod tworzenia wiadomości w tej samej hierarchii. W takiej sytuacji musisz wyraźnie wskazać, który z nich ma korzystać z wstawienia, a który je ignorować.
Jeśli na przykład Twój najbardziej zewnętrzny układ to układ Android View, podczas tworzenia wiadomości używaj wstawienia w systemie widoku i zignoruj je.
Jeśli Twój najbardziej zewnętrzny układ jest kompozycyjny, użyj też zestawów instalacyjnych w funkcji Compose i dodaj odpowiednie elementy kompozycyjne AndroidView
.
Domyślnie każdy zasób ComposeView
wykorzystuje wszystkie wstawki na poziomie wykorzystania (WindowInsetsCompat
). Aby zmienić to domyślne działanie, ustaw opcję ComposeView.consumeWindowInsets
na false
.
Zasoby
- Teraz w Androidzie – w pełni funkcjonalna aplikacja na Androida stworzona w całości przy użyciu Kotlin i Jetpack Compose.
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Komponenty i układy Material Design
- Migracja usługi
CoordinatorLayout
do Compose - Inne uwagi