Podstawy układu tworzenia wiadomości

Jetpack Compose znacznie ułatwia projektowanie i kompilowanie UI aplikacji. Utwórz przekształca stan w elementy interfejsu przez:

  1. Kompozycja elementów
  2. Układ elementów
  3. Rysowanie elementów

Zmienianie stanu tworzenia wiadomości na UI za pomocą kompozycji, układu, rysunku

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:

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:

Dwa elementy tekstowe narysowane na siebie, przez co tekst jest nieczytelny

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")
    }
}

Dwa elementy tekstowe rozmieszczone w układzie kolumnowym, dzięki czemu tekst jest czytelny

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)
        }
    }
}

Pokazuje bardziej złożony układ z małą grafiką obok kolumny elementów tekstowych.

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")
    }
}

Dwa elementy ułożone jeden na drugim

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.

Porównuje 3 proste komponenty układu: kolumnę, wiersz i pole

Aby ustawić pozycję dziecka w elemencie Row, ustaw parametry horizontalArrangement i verticalAlignment argumentów. W przypadku Column ustaw argumenty verticalArrangementhorizontalAlignment:

@Composable
fun ArtistCardArrangement(artist: Artist) {
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.End
    ) {
        Image(bitmap = artist.image, contentDescription = "Artist image")
        Column { /*...*/ }
    }
}

Elementy są wyrównane do prawej

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:

  1. Węzeł główny Row ma wykonać pomiar.
  2. Węzeł główny Row prosi pierwszy element podrzędny, Image, o zmierzenie.
  3. 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.
  4. Węzeł główny Row prosi o dokonanie pomiaru do drugiego węzła podrzędnego, Column.
  5. Węzeł Column prosi pierwszy element podrzędny Text o zmierzenie.
  6. Pierwszy węzeł Text jest węzłem liścia, więc zgłasza rozmiar i zwraca instrukcje dotyczące miejsca docelowego.
  7. Węzeł Column prosi swoje drugie dziecko Text o pomiar.
  8. Drugi węzeł Text jest węzłem-liściem, więc podaje rozmiar i zwraca instrukcje dotyczące umieszczenia.
  9. Po zmierzeniu i umieszczeniu swoich elementów podrzędnych węzła Column może określić własny rozmiar i miejsce docelowe.
  10. Po zmierzeniu i umieszczeniu swoich elementów podrzędnych węzła Row może określić własny rozmiar i miejsce docelowe.

kolejność pomiarów, rozmiarów i miejsc docelowych w drzewie interfejsu wyników wyszukiwania;

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),
        ) { /*...*/ }
    }
}

jeszcze bardziej złożony układ, w którym za pomocą modyfikatorów można zmieniać sposób rozmieszczenia grafiki i określać obszary, które reagują na działania użytkownika;

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:

Diagram pokazujący dostępne miejsca na pasku aplikacji Material Components

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. Scaffoldzapewnia miejsca na najczęściej używane komponenty Material na najwyższym poziomie, takie jak TopAppBar, BottomAppBar, FloatingActionButtonDrawer. Za pomocą Scaffold, możesz łatwo upewnić się, że te komponenty są prawidłowo umieszczone współdziałają ze sobą.

Przykładowa aplikacja JetNews, która używa Scaffold do pozycjonowania wielu elementów

@Composable
fun HomeScreen(/*...*/) {
    ModalNavigationDrawer(drawerContent = { /* ... */ }) {
        Scaffold(
            topBar = { /*...*/ }
        ) { contentPadding ->
            // ...
        }
    }
}

Obecnie nie ma rekomendacji.

na swoje konto Google.