Jetpack Compose ułatwia projektowanie i tworzenie UI aplikacji. Funkcja tworzenia zmienia stan na elementy interfejsu za pomocą:
- Skład elementów
- Układ elementów
- Rysowanie elementów
W tym dokumencie omawiamy układ elementów i wyjaśniamy niektóre z nich, jakie zawiera funkcja Compose, która pomaga rozmieszczać elementy interfejsu.
Cele układów w widoku tworzenia
Implementacja systemu układów w Jetpack Compose ma dwa główne cele:
- Wysoka wydajność
- Możliwość łatwego pisania układów niestandardowych.
Podstawy funkcji kompozycyjnych
Funkcje kompozycyjne to podstawowy element składowy funkcji Compose. Funkcja kompozycyjna to funkcja zwracająca wartość Unit
, która opisuje część interfejsu użytkownika. Ta funkcja pobiera dane wejściowe i generuje informacje wyświetlane na ekranie. Więcej informacji na temat funkcji kompozycyjnych znajdziesz w dokumentacji modelu mentalnego tworzenia.
Funkcja kompozycyjna może emitować kilka elementów interfejsu. Jeśli jednak nie zapewnisz sposobu ich uporządkowania, funkcja tworzenia może rozmieścić elementy w niewłaściwy sposób. Na przykład ten kod generuje 2 elementy tekstowe:
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
Jeśli nie otrzymasz wskazówek dotyczących kolejności elementów, w widoku wiadomości elementy tekstowe będą się nakładać na siebie, co sprawi, że będą nieczytelne:
Aplikacja Compose udostępnia kolekcję gotowych układów, które ułatwiają rozmieszczanie elementów interfejsu i ułatwiają definiowanie własnych, bardziej specjalistycznych układów.
Komponenty układu standardowego
W wielu przypadkach wystarczy po prostu użyć elementów układu standardowego tworzenia wiadomości.
Użyj Column
, aby umieścić elementy w pionie na ekranie.
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
Aby umieścić elementy poziomo na ekranie, użyj wartości Row
. Zarówno Column
, jak i Row
obsługują konfigurowanie wyrównania zawartych w nich elementów.
@Composable fun ArtistCardRow(artist: Artist) { Row(verticalAlignment = Alignment.CenterVertically) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { Text(artist.name) Text(artist.lastSeenOnline) } } }
Korzystając z Box
, możesz umieszczać elementy nad innymi. Box
obsługuje też konfigurowanie określonego wyrównania zawartych w niej elementów.
@Composable fun ArtistAvatar(artist: Artist) { Box { Image(bitmap = artist.image, contentDescription = "Artist image") Icon(Icons.Filled.Check, contentDescription = "Check mark") } }
Często tylko te elementy składowe są potrzebne. Możesz napisać własną funkcję kompozycyjną, aby połączyć te układy w bardziej skomplikowany układ, który pasuje do Twojej aplikacji.
Aby ustawić pozycję elementu podrzędnego w elemencie Row
, użyj argumentów horizontalArrangement
i verticalAlignment
. W przypadku funkcji Column
ustaw argumenty verticalArrangement
i horizontalAlignment
:
@Composable fun ArtistCardArrangement(artist: Artist) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.End ) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { /*...*/ } } }
Model układu
W modelu układu drzewo interfejsu jest układane w jednym przebiegu. Każdy węzeł jest najpierw proszony o zmierzenie siebie, a następnie rekurencyjnie mierzy wszystkie elementy podrzędne, przekazując dzieciom ograniczenia rozmiaru drzewa. Następnie określamy rozmiar i rozmieszczanie węzłów liści, a oszacowane rozmiary i instrukcje dotyczące miejsca docelowego są przesyłane z powrotem do drzewa.
W skrócie rodzice mierzą się przed dziećmi, ale są dopasowywane i umieszczane po nich.
Przyjrzyj się tej funkcji SearchResult
.
@Composable fun SearchResult() { Row { Image( // ... ) Column { Text( // ... ) Text( // ... ) } } }
Ta funkcja generuje następujące drzewo interfejsu użytkownika.
SearchResult
Row
Image
Column
Text
Text
W przykładzie SearchResult
układ drzewa interfejsu ma taką kolejność:
- Węzeł główny
Row
jest objęty pomiarem. - Węzeł główny
Row
prosi o dokonanie pomiaru przez swój pierwszy węzeł podrzędny,Image
. Image
to węzeł liścia (czyli nie ma elementów podrzędnych), więc zgłasza rozmiar i zwraca instrukcje umieszczania.- Węzeł główny
Row
prosi o przeprowadzenie pomiaru drugiego węzła podrzędnego,Column
. - Węzeł
Column
prosi o przeprowadzenie pomiaru pierwszego elementu podrzędnego (Text
). - Pierwszy węzeł
Text
jest węzłem liścia, więc zgłasza rozmiar i zwraca instrukcje miejsca docelowego. - Węzeł
Column
prosi o 2 podrzędny element podrzędnyText
do przeprowadzenia pomiaru. - Drugi węzeł
Text
jest węzłem liścia, więc zgłasza rozmiar i zwraca instrukcje miejsca docelowego. - Gdy węzeł
Column
zmierzył, zmienił rozmiar i umieścił swoje elementy podrzędne, może określić swój rozmiar i miejsce docelowe. - Gdy węzeł główny
Row
zmierzył, określił rozmiar i umieścił swoje elementy podrzędne, może określić swój rozmiar i miejsce docelowe.
Wyniki
Tworzenie osiąga wysoką skuteczność, ponieważ mierzy dane podrzędne tylko raz. Pomiar jednoprzebiegowy dobrze zwiększa wydajność, ponieważ umożliwia usłudze Compose skuteczne obsługę głębokich drzew interfejsu. Jeśli dany element zmierzyłby swoje podrzędne dwa razy, a to dziecko dwa razy itd., pojedyncza próba utworzenia układu interfejsu musiałaby wymagać dużo pracy, co utrudniałoby utrzymanie wydajności aplikacji.
Jeśli z jakiegoś powodu układ wymaga wielu pomiarów, możesz użyć specjalnego systemu do obsługi pomiarów wewnętrznych. Więcej informacji o tej funkcji znajdziesz w artykule o pomiarach wewnętrznych w układach tworzenia wiadomości.
Pomiar i umiejscowienie to odrębne podfazy przekazywania układu, dlatego wszystkie zmiany, które mają wpływ tylko na rozmieszczenie elementów, a nie na pomiary, mogą być wprowadzane oddzielnie.
Używanie modyfikatorów w układach
Jak wspomnieliśmy w sekcji Modyfikatory tworzenia wiadomości, za pomocą tych modyfikatorów możesz dekorować i ulepszać kompozycje. Modyfikatory są niezbędne
do dostosowywania układu. Na przykład tutaj łączy kilka modyfikatorów, aby dostosować element ArtistCard
:
@Composable fun ArtistCardModifiers( artist: Artist, onClick: () -> Unit ) { val padding = 16.dp Column( Modifier .clickable(onClick = onClick) .padding(padding) .fillMaxWidth() ) { Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ } Spacer(Modifier.size(padding)) Card( elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), ) { /*...*/ } } }
W kodzie powyżej zwróć uwagę na różne funkcje modyfikatorów stosowane razem.
clickable
reaguje na dane wejściowe użytkownika i pokazuje fali.padding
umieszcza odstęp wokół elementu.fillMaxWidth
sprawia, że funkcja kompozycyjna wypełnia maksymalną szerokość, którą otrzymuje od elementu nadrzędnego.size()
określa preferowaną szerokość i wysokość elementu.
Układy z możliwością przewijania
Więcej informacji o układach z możliwością przewijania znajdziesz w dokumentacji gestów tworzenia.
Listy i leniwe listy znajdziesz w dokumentacji tworzenia list.
Układy elastyczne
Układ powinien być projektowany z uwzględnieniem różnych orientacji i rozmiarów ekranu. Funkcja tworzenia oferuje od razu kilka mechanizmów ułatwiających dostosowywanie układów kompozycyjnych do różnych konfiguracji ekranu.
Ograniczenia
Aby poznać ograniczenia pochodzące z elementu nadrzędnego i zaprojektować odpowiedni układ, możesz użyć właściwości BoxWithConstraints
. Ograniczenia dotyczące pomiarów można znaleźć w zakresie funkcji lambda dotyczącej treści. Korzystając z tych ograniczeń pomiarowych, możesz tworzyć różne układy dostosowane do różnych konfiguracji ekranu:
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
Układy oparte na boksach
Narzędzie Compose udostępnia szeroką gamę funkcji kompozycyjnych opartych na Material Design z zależność androidx.compose.material:material
(która jest dostępna podczas tworzenia projektu tworzenia w Android Studio), co ułatwia tworzenie interfejsu. Dostępne są takie elementy jak Drawer
, FloatingActionButton
i TopAppBar
.
Komponenty Material Design intensywnie wykorzystują interfejsy API boksów reklamowych. Wprowadzany jest wzór do tworzenia wiadomości, który dodaje warstwę dostosowywania do elementów kompozycyjnych. Takie podejście zwiększa elastyczność komponentów, ponieważ przyjmują element podrzędny, który można skonfigurować samodzielnie, zamiast ujawniać każdy parametr konfiguracji elementu podrzędnego.
Pozostawiają one puste miejsce w interfejsie, które deweloper może wypełnić według własnego uznania. Są to na przykład przedziały, które możesz dostosować w elemencie TopAppBar
:
Elementy kompozycyjne zwykle korzystają z funkcji lambda kompozycyjnej content
( content: @Composable
() -> Unit
). Interfejsy API przedziałów udostępniają wiele parametrów content
do konkretnych zastosowań.
Na przykład TopAppBar
umożliwia podzielenie się treściami do title
, navigationIcon
i actions
.
Na przykład
Scaffold
umożliwia wdrożenie interfejsu użytkownika z podstawową strukturą układu Material Design.
Scaffold
Udostępnia boksy na najpopularniejsze komponenty Material najwyższego poziomu,
takie jak TopAppBar
,
BottomAppBar
,
FloatingActionButton
i Drawer
. Używając atrybutu Scaffold
, można łatwo zadbać o to, aby komponenty te były prawidłowo umiejscowione i prawidłowo ze sobą współdziałały.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony
- Modyfikatory tworzenia wiadomości
- Kotlin dla Jetpack Compose
- Komponenty i układy Material Design