Platforma Android odpowiada za wyświetlanie interfejsu użytkownika systemu, takiego jak pasek stanu i pasek nawigacyjny. Ten interfejs systemu jest wyświetlany niezależnie od tego, z której aplikacji korzysta użytkownik.
WindowInsets
zawiera informacje o interfejsie użytkownika systemu, aby aplikacja rysowała w odpowiednim miejscu i nie była przysłonięta przez interfejs systemu.
![Wypełnianie od krawędzi do krawędzi, aby rysować za paskami systemu](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/insets/e2e-intro.gif?hl=pl)
W Androidzie 14 (poziom interfejsu API 34) i starszych interfejs aplikacji domyślnie nie jest wyświetlany pod paskami systemowymi ani wycięciami w ekranie.
W Androidzie 15 (poziom interfejsu API 35) i nowszych aplikacja jest wyświetlana pod paskami systemu i wycięciami ekranu, gdy jest kierowana na pakiet SDK 35. Dzięki temu użytkownicy będą mogli wygodniej korzystać z aplikacji, która będzie mogła w pełni wykorzystać dostępną przestrzeń okna.
Wyświetlanie treści za interfejsem systemu nazywa się wypełnianiem ekranu. Na tej stronie dowiesz się więcej o różnych typach wstawek, o tym, jak przejść od krawędzi do krawędzi, oraz o tym, jak używać interfejsów API wstawek do animowania interfejsu użytkownika i unikania zasłaniania zawartości aplikacji przez elementy interfejsu systemu.
.Podstawy wstawek
Gdy aplikacja zajmuje cały ekran, musisz zadbać o to, aby ważne treści i interakcje nie były zasłonięte przez interfejs systemu. Jeśli na przykład przycisk znajduje się za paskiem nawigacji, użytkownik może nie mieć możliwości jego kliknięcia.
Rozmiar interfejsu systemu i informacje o jego umieszczeniu są określane za pomocą insetów.
Każda część interfejsu systemu ma odpowiedni typ wstawki, który opisuje jej rozmiar i miejsce umieszczenia. Na przykład w ramkach paska stanu podajesz rozmiar i położenie paska stanu, a w ramkach paska nawigacji – rozmiar i położenie paska nawigacji. Każdy typ wstawki składa się z 4 wymiarów pikseli: góra, lewo, prawo i dół. Te wymiary określają, jak daleko interfejs systemu sięga od odpowiednich stron okna aplikacji. Aby uniknąć nakładania się na ten typ interfejsu systemu, interfejs aplikacji musi być wsunięty o tę odległość.
Te wbudowane typy wstawek na Androidzie są dostępne w WindowInsets
:
Wstawki opisujące paski stanu. To górne paski interfejsu systemu zawierające ikony powiadomień i inne wskaźniki. |
|
Pasek stanu jest wsunięty, gdy jest widoczny. Jeśli paski stanu są obecnie ukryte (z powodu przejścia w tryb pełnoekranowy), wstawki głównego paska stanu będą puste, ale nie będą puste wstawki paska stanu. |
|
Wstawki opisujące paski nawigacyjne. Są to paski interfejsu systemu po lewej, prawej lub dolnej stronie urządzenia, które opisują pasek zadań lub ikony nawigacyjne. Mogą się one zmieniać w czasie działania aplikacji w zależności od preferowanej przez użytkownika metody nawigacji i interakcji z paskiem aplikacji. |
|
Pasek nawigacyjny w przypadku, gdy jest widoczny. Jeśli paski nawigacyjne są obecnie ukryte (z powodu przejścia do trybu pełnoekranowego), wstawki głównego paska nawigacyjnego będą puste, ale nie będą puste. |
|
Wstawka opisująca dekorację okna interfejsu użytkownika, jeśli jest to okno swobodne, np. górny pasek tytułu. |
|
Pasek napisów jest wsunięty, gdy jest widoczny. Jeśli paski napisów są obecnie ukryte, wstawki głównego paska napisów będą puste, ale nie będą puste. |
|
Zbiór elementów paska systemu, w tym paski stanu, paski nawigacyjne i paski nagłówków. |
|
Wstawki paska systemowego, gdy są widoczne. Jeśli paski systemu są obecnie ukryte (z powodu przejścia w tryb pełnoekranowy), główne wstawki paska systemu będą puste, ale te wstawki nie będą puste. |
|
Wstawki opisujące ilość miejsca na dole, którą zajmuje klawiatura ekranowa. |
|
Wstawki opisujące ilość miejsca, którą zajmowała klawiatura programowa przed animacją bieżącej klawiatury. |
|
Wstawki opisujące ilość miejsca, jaką zajmie klawiatura programowa po animacji bieżącej klawiatury. |
|
Rodzaj wstawek opisujących bardziej szczegółowe informacje o interfejsie nawigacji, podając ilość miejsca, w którym „dotknięcia” będą obsługiwane przez system, a nie aplikację. W przypadku przezroczystych pasków nawigacji z gestami niektóre elementy aplikacji można dotknąć za pomocą interfejsu nawigacji systemu. |
|
Elementy, które można kliknąć, są wstawione, gdy są widoczne. Jeśli elementy, które można kliknąć, są obecnie ukryte (z powodu przejścia w tryb pełnoekranowy), wstawione elementy główne będą puste, ale wstawione elementy będą niepuste. |
|
Wstawki reprezentujące liczbę wstawek, w których system przechwytuje gesty nawigacyjne. Aplikacje mogą ręcznie określić obsługę ograniczonej liczby tych gestów za pomocą |
|
Podzbiór gestów systemowych, które zawsze będą obsługiwane przez system i których nie można wyłączyć za pomocą |
|
Wstawki przedstawiające odstęp potrzebny, aby uniknąć nakładania się na wycięcie w ekranie (notch lub pinhole). |
|
Wstawki przedstawiające zakrzywione obszary wyświetlania typu kaskada. Wyświetlacz typu wodospad ma zaokrąglone obszary na krawędziach ekranu, gdzie ekran zaczyna się zawijać wzdłuż boków urządzenia. |
Te typy są podsumowane przez 3 „bezpieczne” typy wstawek, które zapewniają, że treści nie są zasłonięte:
Te „bezpieczne” typy wstawek chronią treści na różne sposoby w zależności od wstawek na platformie:
- Użyj
WindowInsets.safeDrawing
, aby chronić treści, które nie powinny być wyświetlane pod interfejsem systemu. Jest to najczęstsze zastosowanie wstawek: zapobieganie zasłanianiu treści przez interfejs systemu (częściowo lub całkowicie). - Użyj
WindowInsets.safeGestures
, aby chronić treści za pomocą gestów. Zapobiega to konfliktom gestów systemowych z gestami w aplikacji (np. w przypadku dolnego paska, karuzeli lub gier). - Użyj właściwości
WindowInsets.safeContent
jako kombinacji właściwościWindowInsets.safeDrawing
iWindowInsets.safeGestures
, aby upewnić się, że zawartość nie ma nakładania się wizualnego ani nakładania się gestów.
Konfiguracja wkładek
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ą.
- Kieruj na pakiet SDK 35 lub nowszy, aby wymusić wyświetlanie bez ramki na urządzeniach z Androidem 15 lub nowszym. Aplikacja wyświetla się za interfejsem systemu. Możesz dostosować interfejs aplikacji, obsługując wstawki.
- Opcjonalnie możesz wywołać
enableEdgeToEdge()
wActivity.onCreate()
, co pozwoli aplikacji wyświetlać się bez ramki w poprzednich wersjach Androida. Ustaw wartość
android:windowSoftInputMode="adjustResize"
w poluAndroidManifest.xml
w sekcji Aktywność. To ustawienie pozwala aplikacji odbierać rozmiar interfejsu IME jako wstawkę, którą możesz wykorzystać do wypełnienia i odpowiedniego rozmieszczenia treści, gdy interfejs 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 do tworzenia
Gdy 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 mają być stosowane wstawki. Możesz to zrobić na poziomie ekranu lub 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 używania tych typów wstawek do dostosowywania układów kompozytowych: modyfikatory wypełniania i modyfikatory rozmiaru wstawki.
Modyfikatory wypełniania
Modifier.windowInsetsPadding(windowInsets: WindowInsets)
stosuje podane wcięcia 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ą ilość wstawionych okien, ustawiając rozmiar komponentu na rozmiar wstawionych okien:
Stosuje stronę początkową windowInsets jako szerokość (np. |
|
Stosuje końcową stronę zaokrąglenia okna jako szerokość (jak |
|
Stosuje górną stronę zawijania okna jako wysokość (np. |
|
|
Dolny bok windowInsets jest stosowany jako wysokość (np. |
Te modyfikatory są szczególnie przydatne do ustawiania rozmiaru Spacer
, który zajmuje miejsce w ramkach:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
Konsumpcja w ramce
Modyfikatory wypełniania w ramce (windowInsetsPadding
i elementy pomocnicze, takie jak safeDrawingPadding
) automatycznie wykorzystują część wstawionych elementów, która jest stosowana jako wypełnienie. Wchodząc głębiej w drzewo kompozycji, wiesz, że wpisane modyfikatory wypełniania wgłębienia i modyfikatory rozmiaru wgłębienia wiedzą, że część wgłębień została już wykorzystana przez zewnętrzne modyfikatory wypełniania wgłębienia. Unikaj używania tej samej części wgłębień więcej niż raz, ponieważ spowodowałoby to zbyt dużo dodatkowego miejsca.
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 wstawione elementy animują się, aby dopasować się do jej rozmiaru, a modyfikator imePadding()
zacznie stosować wypełnienie dolne, aby dopasować rozmiar LazyColumn
do otwierającej się 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ść elementu Spacer
wynosi 0.
Gdy IME się zamyka, zmiany zachodzą w odwrotnej kolejności: gdy imePadding()
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.Spacer
TextField
.Takie zachowanie jest osiągane dzięki komunikacji między wszystkimi modyfikatorami windowInsetsPadding
i może być modyfikowane na kilka innych 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.
Ze względu na poniższe zastrzeżenia zalecamy jednak, 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óźniej. Zdefiniowane na tej stronie modyfikatory są zaprojektowane tak, aby opóźniać używanie wartości w ramkach do momentu fazy układu. Dzięki temu wartości w ramkach są używane w tym samym ujęciu, w którym są aktualizowane.
Animacje klawiatury IME z WindowInsets
Możesz zastosować Modifier.imeNestedScroll()
do ruchomego kontenera, aby automatycznie otwierać i zamykać IME, gdy przewijasz do dołu kontenera.
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") } } }
![Animacja pokazująca element interfejsu przewijany w górę i w dół, aby zrobić miejsce na klawiaturę](https://developer.android.google.cn/static/develop/ui/compose/images/interop-keyboard.gif?hl=pl)
Obsługa wstawionych komponentów Material 3
Dla wygody użytkowników wiele wbudowanych komponentów w Material 3 (androidx.compose.material3
) samodzielnie obsługuje wstawione elementy na podstawie tego, jak komponenty są umieszczone w aplikacji zgodnie ze specyfikacją Material.
Obsługa funkcji kompozycyjnych w ramce
Poniżej znajduje się lista komponentów Material Design, które automatycznie obsługują wstawienia.
Paski aplikacji
TopAppBar
/SmallTopAppBar
/CenterAlignedTopAppBar
/MediumTopAppBar
/LargeTopAppBar
: stosuje górne i poziome strony pasków systemu jako wypełnienie, ponieważ jest używane u góry okna.BottomAppBar
: dopełnienie dołu i poziomych stron pasków systemu.
Kontenery treści
ModalDrawerSheet
/DismissibleDrawerSheet
/PermanentDrawerSheet
(treści w modale paska nawigacyjnego): stosuje wewnętrzne i początkowe wcięcia do treści.ModalBottomSheet
: zastosuj dolne wcięcia.NavigationBar
: zastosowanie dolnej i poziomej wkładki.NavigationRail
: stosuje wstawki pionowe i początkowe.
Rusztowanie
Domyślnie funkcja Scaffold
udostępnia wstawki jako parametr paddingValues
, który możesz wykorzystać.
Scaffold
nie stosuje wstawek do treści; ta odpowiedzialność spoczywa na użytkowniku.
Aby na przykład użyć tych wstawek z LazyColumn
w ramach 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]) ) } } }
Ten film pokazuje LazyColumn
w ramach Scaffold
z wyświetlaczem od krawędzi do krawędzi wyłączonym i włączonym:
Zastępowanie domyślnych wstawek
Aby skonfigurować zachowanie komponentu, możesz zmienić parametr windowInsets
przekazywany do niego. Ten parametr może być innym typem wstawionego okna, który ma być zastosowany, lub może być wyłączony przez podanie pustej instancji: WindowInsets(0, 0, 0, 0)
.
Aby na przykład wyłączyć obsługę wstawionych elementów w LargeTopAppBar
, ustaw parametr windowInsets
na pustą instancję:
LargeTopAppBar( windowInsets = WindowInsets(0, 0, 0, 0), title = { Text("Hi") } )
Współdziałanie z wstawkami systemu View
Jeśli Twoja aplikacja zawiera kod zarówno dla widoku Compose, jak i View, może być konieczne określenie, które wstawione elementy systemu powinien używać każdy z nich, oraz upewnienie się, że są one wysyłane do widoków nadrzędnych.
Zastępowanie domyślnych wstawek
Jeśli na ekranie znajdują się zarówno widoki, jak i kod Compose w ramach tej samej hierarchii, może być konieczne zastąpienie domyślnych wstawek. W takim przypadku musisz wyraźnie określić, która z nich powinna używać wstawek, a która powinna je ignorować.
Jeśli na przykład najszerszy układ jest układem Android View, powinieneś używać wstawek w systemie View i ignorować je w Compose.
Jeśli natomiast zewnętrzny układ jest składanym elementem, musisz użyć w Compose wbudowanych elementów i odpowiednio wypełnić AndroidView
.
Domyślnie każdy element ComposeView
zużywa wszystkie wstawione elementy na poziomie WindowInsetsCompat
. Aby zmienić to domyślne działanie, ustaw wartość ComposeView.consumeWindowInsets
na false
.
Zgodność wsteczna w przypadku wysyłania wstawionych widoków
Jeśli Twoja aplikacja zawiera kod Views, konieczne może być potwierdzenie, że wstawki są wysyłane do podrzędnych widoków na urządzeniach z Androidem 10 (poziom interfejsu API 29) lub starszym. Więcej informacji znajdziesz w przewodniku po widokach od krawędzi do krawędzi.
Ikony na pasku systemu
Wywołanie enableEdgeToEdge
zapewnia aktualizację kolorów ikon na pasku systemu po zmianie motywu urządzenia.
Podczas przekształcania aplikacji na tryb pełnoekranowy może być konieczne ręczne zaktualizowanie kolorów ikony na pasku systemowym, aby kontrastowały z tłem aplikacji. Aby na przykład utworzyć jasne ikony paska stanu:
Kotlin
WindowCompat.getInsetsController(window, window.decorView) .isAppearanceLightStatusBars = false
Java
WindowCompat.getInsetsController(window, window.getDecorView()) .setAppearanceLightStatusBars(false);
Ochrona paska systemu
Gdy aplikacja będzie kierowana na pakiet SDK 35 lub nowszy, wyświetlanie bez ramki będzie wymuszane. Pasek stanu systemu i paski nawigacji przy użyciu gestów są przezroczyste, ale pasek nawigacji z 3 przyciskami jest półprzezroczysty.
Aby usunąć domyślną przezroczystą ochronę tła nawigacji z 3 przyciskami, ustaw wartość Window.setNavigationBarContrastEnforced
na false
.
Materiały
- paski systemu Android, wskazówki dotyczące projektowania paska systemu
- Now in Android – w pełni funkcjonalna aplikacja na Androida, która została w pełni napisana w Kotlinie i Jetpack Compose.
- Obsługa wymogów dotyczących wyświetlania bez ramki w Androidzie 15 – ćwiczenie z programowania dotyczące wymogów dotyczących wyświetlania bez ramki w Androidzie 15
- Wskazówki dotyczące obsługi wcięć w Androidzie 15 z wymuszonym wyświetlaniem od krawędzi do krawędzi
- Podgląd i testowanie interfejsu od krawędzi do krawędzi
- 3 sposoby na lepsze korzystanie z aplikacji na Androida: Edge to Edge, przewidywanie wsteczne i przeglądanie – film w YouTube o wdrożeniu Edge to Edge w Androidzie 15
- Od krawędzi do krawędzi i w ramce | Wskazówki dotyczące tworzenia kompozycji – film w YouTube pokazujący, jak korzystać z ramek, aby rysować od krawędzi do krawędzi
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Komponenty i układy w Material Design
- Migracja
CoordinatorLayout
do tworzenia wiadomości - Inne kwestie