Jetpack Compose znacznie ułatwia projektowanie i kompilowanie UI aplikacji. Utwórz przekształca stan w elementy interfejsu przez:
- Kompozycja elementów
- Układ elementów
- Rysowanie elementów
Ten dokument skupia się na układzie elementów i objaśnia niektóre które pomagają w rozmieszczaniu elementów interfejsu użytkownika.
Cele układów w polu tworzenia wiadomości
Implementacja systemu układu w Jetpack Compose ma 2 główne cele:
- Wysoka wydajność
- możliwość łatwego tworzenia niestandardowych układów,
Podstawowe informacje o funkcjach kompozycyjnych
Funkcje kompozycyjne to podstawowy element składowy funkcji Compose. Funkcja składana to funkcja emitująca Unit
, która opisuje część interfejsu użytkownika. Funkcja ta przyjmuje dane wejściowe i generuje to, co jest widoczne na ekranie. Więcej
informacji na temat utworów kompozycyjnych, spójrz na sposób tworzenia
model.
Funkcja kompozycyjna może generować kilka elementów interfejsu. Jeśli jednak nie podasz wskazówek dotyczących ich rozmieszczenia, Compose może umieścić elementy w nieodpowiednim miejscu. Ten kod generuje na przykład 2 elementy tekstowe:
@Composable fun ArtistCard() { Text("Alfred Sisley") Text("3 minutes ago") }
Bez wskazówek dotyczących układu elementów tekstowych Compose układa je jeden na drugim, przez co stają się one nieczytelne:
Tworzenie wiadomości zawiera kolekcję gotowych układów, które pomogą Ci uporządkować elementów interfejsu i ułatwia definiowanie własnych, bardziej dopracowanych układów.
Komponenty standardowego układu
W wielu przypadkach możesz po prostu użyć standardowych elementów układu w Compose.
Użyj Column
, aby umieścić elementy na ekranie w orientacji pionowej.
@Composable fun ArtistCardColumn() { Column { Text("Alfred Sisley") Text("3 minutes ago") } }
Podobnie możesz użyć Row
, aby umieścić elementy poziomo na ekranie. Zarówno element Column
, jak i element Row
umożliwiają konfigurowanie wyrównania elementów, które zawierają.
@Composable fun ArtistCardRow(artist: Artist) { Row(verticalAlignment = Alignment.CenterVertically) { Image(bitmap = artist.image, contentDescription = "Artist image") Column { Text(artist.name) Text(artist.lastSeenOnline) } } }
Aby umieścić elementy jeden na drugim, użyj Box
. Box
umożliwia też skonfigurowanie konkretnego wyrównania zawartych w nim elementów.
@Composable fun ArtistAvatar(artist: Artist) { Box { Image(bitmap = artist.image, contentDescription = "Artist image") Icon(Icons.Filled.Check, contentDescription = "Check mark") } }
Często te elementy są wszystkim, czego potrzebujesz. Możesz napisać własną funkcję kompozycyjną, aby połączyć te układy w bardziej skomplikowany układ pasujący do Twojej aplikacji.
Aby ustawić pozycję dziecka w elemencie Row
, ustaw parametry horizontalArrangement
i
verticalAlignment
argumentów. W przypadku 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 przejeździe. Każdy węzeł jest najpierw poprosiliśmy o pomiar, a potem rekurencyjnie mierz wszystkie dzieci. ograniczeń rozmiaru w dół drzewa. Następnie określa się rozmiary i miejsce umieszczenia węzłów liści, a rozwiązane rozmiary i instrukcje dotyczące umieszczenia są przekazywane z powrotem do drzewa.
Krótko mówiąc, rodzice mierzą się przed dziećmi, ale ich rozmiar i pozycja są określane po ich dzieciach.
Rozważ poniższą funkcję SearchResult
.
@Composable fun SearchResult() { Row { Image( // ... ) Column { Text( // ... ) Text( // ... ) } } }
Ta funkcja zwraca poniższe drzewo interfejsu.
SearchResult
Row
Image
Column
Text
Text
W przykładzie SearchResult
układ drzewa interfejsu użytkownika jest następujący:
- Węzeł główny
Row
ma wykonać pomiar. - Węzeł główny
Row
prosi pierwszy element podrzędny,Image
, o zmierzenie. Image
jest węzłem liścia (czyli nie ma elementów potomnych), więc zgłasza rozmiar i zwraca instrukcje dotyczące miejsca docelowego.- Węzeł główny
Row
prosi o dokonanie pomiaru do drugiego węzła podrzędnego,Column
. - Węzeł
Column
prosi pierwszy element podrzędnyText
o zmierzenie. - Pierwszy węzeł
Text
jest węzłem liścia, więc zgłasza rozmiar i zwraca instrukcje dotyczące miejsca docelowego. - Węzeł
Column
prosi swoje drugie dzieckoText
o pomiar. - Drugi węzeł
Text
jest węzłem-liściem, więc podaje rozmiar i zwraca instrukcje dotyczące umieszczenia. - Po zmierzeniu i umieszczeniu swoich elementów podrzędnych węzła
Column
może określić własny rozmiar i miejsce docelowe. - Po zmierzeniu i umieszczeniu swoich elementów podrzędnych węzła
Row
może określić własny rozmiar i miejsce docelowe.
Wydajność
Tworzenie wiadomości osiąga wysoką skuteczność dzięki mierzeniu aktywności dzieci tylko raz. Jednoprzepustowe i zwiększają wydajność, umożliwiając tworzenie Drzewa interfejsu. Jeśli element zmierzył swoje dziecko dwukrotnie, a ten sam pomiarem każdego z swoje dzieci dwukrotnie i tak dalej, jedna próba rozmieszczenia całego interfejsu włożyć dużo pracy, przez co ciężko jest dbać o wydajność aplikacji.
Jeśli układ wymaga z jakiegoś powodu kilku pomiarów, Compose oferuje specjalny system pomiarów wewnętrznych. Więcej informacji o tej funkcji znajdziesz w pomiarach wewnętrznych w Compose układy scalone.
Ponieważ pomiar i rozmieszczenie to odrębne etapy przepływu układu, wszelkie zmiany, które wpływają tylko na rozmieszczenie elementów, a nie na pomiar, mogą być wykonywane osobno.
Używanie modyfikatorów w układach
Jak wspomnieliśmy w artykule o modyfikatorach tworzenia wiadomości, możesz używać
modyfikatory do dekorowania lub rozszerzania elementów kompozycyjnych. Modyfikatory są niezbędne do dostosowywania układu. Na przykład tworzymy łańcuch kilku modyfikatorów
aby dostosować 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), ) { /*...*/ } } }
Zwróć uwagę, że w powyższym kodzie są używane różne funkcje modyfikujące.
clickable
powoduje, że funkcja kompozycyjna reaguje na dane wejściowe użytkownika i wykazuje falę.padding
umieszcza przestrzeń wokół elementu.fillMaxWidth
sprawia, że wypełnienie kompozycyjne ma maksymalną szerokość podaną mu z jego elementu nadrzędnego.size()
określa preferowaną szerokość i wysokość elementu.
Przewijane układy
Więcej informacji o przewijanych układach znajdziesz w dokumentacji gestów w komponowaniu wiadomości.
Informacje o listach i leniwych listach znajdziesz w Dokumentacja tworzenia list
Układy elastyczne
Układ powinien być zaprojektowany z uwzględnieniem różnych orientacji ekranu i rozmiarów. Funkcja tworzenia wiadomości oferuje od razu kilka mechanizmów ułatwia dostosowywanie układów kompozycyjnych do różnych konfiguracji ekranu.
Ograniczenia
Aby poznać ograniczenia pochodzące z elementu nadrzędnego i odpowiednio zaprojektować układ, możesz użyć BoxWithConstraints
. Ograniczenia pomiarów można znaleźć w zakresie lambda treści. Za pomocą tych pomiarów możesz:
ograniczeń do tworzenia różnych układów dla różnych konfiguracji ekranu:
@Composable fun WithConstraintsComposable() { BoxWithConstraints { Text("My minHeight is $minHeight while my maxWidth is $maxWidth") } }
Układy oparte na slotach
W aplikacji Compose znajdziesz wiele różnych funkcji kompozycyjnych opartych na materiale
projektuj za pomocą
zależność androidx.compose.material:material
(uwzględniana podczas tworzenia
utwórz projekt w Android Studio), aby ułatwić tworzenie UI. Dostępne są elementy Drawer
, FloatingActionButton
i TopAppBar
.
Komponenty Material Design intensywnie korzystają z interfejsów API slotów, czyli wzoru, który wdrożono w Compose, aby umożliwić dostosowanie komponentów składanych. Takie podejście sprawia,
bardziej elastyczne, ponieważ akceptują element podrzędny, który można konfigurować
samodzielnie, a nie musisz ujawniać każdego parametru konfiguracji podrzędnego.
Przedziały pozostawiają w interfejsie puste miejsce, w którym deweloper może wypełniać je według własnego uznania. Na przykład w usługach TopAppBar
możesz dostosować te sloty:
Elementy kompozycyjne zwykle używają funkcji lambda kompozycyjnej content
( content: @Composable
() -> Unit
). Interfejsy API przedziałów udostępniają wiele parametrów content
do określonych zastosowań.
Na przykład TopAppBar
umożliwia przekazanie treści do title
,
navigationIcon
i actions
.
Na przykład:
Scaffold
pozwala na implementację interfejsu z podstawową strukturą układu Material Design.
Scaffold
zapewnia miejsca na najczęściej używane komponenty Material na najwyższym poziomie, takie jak TopAppBar
,
BottomAppBar
,
FloatingActionButton
i Drawer
. Za pomocą
Scaffold
, możesz łatwo upewnić się, że te komponenty są prawidłowo umieszczone
współdziałają ze sobą.
@Composable fun HomeScreen(/*...*/) { ModalNavigationDrawer(drawerContent = { /* ... */ }) { Scaffold( topBar = { /*...*/ } ) { contentPadding -> // ... } } }
Obecnie nie ma rekomendacji.
Zaloguj się na swoje konto Google.