W Compose elementy interfejsu są reprezentowane przez funkcje kompozycyjne, które generują
części interfejsu użytkownika przy wywołaniu. Jest on dodawany do drzewa UI, który jest renderowany
na ekranie. Każdy element interfejsu ma jednego rodzica i potencjalnie wiele elementów podrzędnych. Każdy element jest też umieszczony w swoim elemencie nadrzędnym, z położeniem określonym jako współrzędne (x, y) oraz rozmiarem określonym jako width
i height
.
Rodzice definiują ograniczenia dla elementów podrzędnych. Element musi określić swój rozmiar w ramach tych ograniczeń. Ograniczenia ograniczają minimalną i maksymalną wartość width
oraz height
elementu. Jeśli element ma elementy podrzędne, może mierzyć każdy z nich, aby określić swój rozmiar. Gdy element określi i zgłosi swój rozmiar, może określić, jak umieścić elementy podrzędne względem siebie. Szczegółowe informacje na ten temat znajdziesz w artykule Tworzenie niestandardowych układów.
Umieszczanie każdego węzła w drzewie interfejsu to proces 3-etapowy. Każdy węzeł musi:
- Mierz wszystkie dzieci
- określać własny rozmiar,
- Umieść elementy podrzędne
Zastosowanie zakresów określa, kiedy możesz mierzyć i umieszczać dzieci.
Pomiar układu można przeprowadzić tylko podczas pomiaru i przesyłania układu, a element podrzędny można umieścić tylko podczas przesyłania układu (i tylko po jego zmierzeniu). Ze względu na zakresy tworzenia wiadomości, takie jak
MeasureScope
,
i PlacementScope
,
jest wymuszane podczas kompilacji.
Używanie modyfikatora układu
Aby zmienić sposób pomiaru i układu elementu, możesz użyć modyfikatora layout
na zewnątrz. Layout
to funkcja lambda; w jego parametrach
obejmują m.in. element, który można zmierzyć
przekazywane jako measurable
, a ograniczenia przychodzące funkcji kompozycyjnej przekazywane jako
constraints
Modyfikator niestandardowego układu może wyglądać tak:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Wyświetlmy na ekranie Text
i zmodyfikujmy odległość od górnej krawędzi do linii bazowej pierwszego wiersza tekstu. Właśnie to robi modyfikator paddingFromBaseline
, który implementujemy tutaj jako przykład.
Aby to zrobić, użyj modyfikatora layout
i ręcznie umieść funkcję kompozycyjną w elemencie
ekranu. Oto oczekiwane działanie, w przypadku którego dopełnienie u góry Text
jest ustawione na 24.dp
:
Oto kod, który powoduje takie odstępy:
fun Modifier.firstBaselineToTop( firstBaselineToTop: Dp ) = layout { measurable, constraints -> // Measure the composable val placeable = measurable.measure(constraints) // Check the composable has a first baseline check(placeable[FirstBaseline] != AlignmentLine.Unspecified) val firstBaseline = placeable[FirstBaseline] // Height of the composable with padding - first baseline val placeableY = firstBaselineToTop.roundToPx() - firstBaseline val height = placeable.height + placeableY layout(placeable.width, height) { // Where the composable gets placed placeable.placeRelative(0, placeableY) } }
Oto, co się dzieje w tym kodzie:
- W parametrze lambda
measurable
mierzysz wartośćText
reprezentowaną przez parametr mierzalny, wywołując funkcjęmeasurable.measure(constraints)
. - Rozmiar elementu kompozytowego określasz, wywołując metodę
layout(width, height)
, która zwraca też funkcję lambda używaną do umieszczania owiniętych elementów. W tym przypadku jest to wysokość między ostatnią linią bazową a dodanym górnym wypełnieniem. - Aby ustawić opakowane elementy na ekranie, wywołaj funkcję
placeable.place(x, y)
. Jeśli owinięte elementy nie zostaną umieszczone, nie będą widoczne. Pozycjay
odpowiada górnemu wypełnieniu – pozycji pierwszej linii tekstu.
Aby sprawdzić, czy wszystko działa zgodnie z oczekiwaniami, użyj tego modyfikatora w elemencie Text
:
@Preview @Composable fun TextWithPaddingToBaselinePreview() { MyApplicationTheme { Text("Hi there!", Modifier.firstBaselineToTop(32.dp)) } } @Preview @Composable fun TextWithNormalPaddingPreview() { MyApplicationTheme { Text("Hi there!", Modifier.padding(top = 32.dp)) } }
Tworzenie układów niestandardowych
Modyfikator layout
zmienia tylko funkcję wywoływania kompozycyjnego. Do pomiaru i układu
wielu elementów kompozycyjnych, użyj funkcji Layout
. Ta kompozycja umożliwia ręczne pomiar i rozmieszczenie elementów podrzędnych. Wszystkie układy wyższego poziomu, takie jak Column
i Row
, są tworzone za pomocą komponentu Layout
.
Stwórzmy podstawową wersję interfejsu Column
. Większość układów niestandardowych ma taki schemat:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // measure and position children given constraints logic here // ... } }
Podobnie jak modyfikator layout
, measurables
to lista elementów podrzędnych, które
które należy objąć pomiarem, a constraints
to ograniczenia z elementu nadrzędnego.
Zgodnie z tą samą logiką co wcześniej MyBasicColumn
można zastosować w ten sposób:
@Composable fun MyBasicColumn( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( modifier = modifier, content = content ) { measurables, constraints -> // Don't constrain child views further, measure them with given constraints // List of measured children val placeables = measurables.map { measurable -> // Measure each children measurable.measure(constraints) } // Set the size of the layout as big as it can layout(constraints.maxWidth, constraints.maxHeight) { // Track the y co-ord we have placed children up to var yPosition = 0 // Place children in the parent layout placeables.forEach { placeable -> // Position item on the screen placeable.placeRelative(x = 0, y = yPosition) // Record the y co-ord placed up to yPosition += placeable.height } } } }
Podrzędne elementy kompozycyjne są ograniczone przez ograniczenia Layout
(bez
minHeight
) i są one umieszczane na podstawie yPosition
funkcji
poprzedniego elementu kompozycyjnego.
Oto, jak można używać niestandardowego komponentu:
@Composable fun CallingComposable(modifier: Modifier = Modifier) { MyBasicColumn(modifier.padding(8.dp)) { Text("MyBasicColumn") Text("places items") Text("vertically.") Text("We've done it by hand!") } }
Kierunek układu
Zmień kierunek układu kompozytowego, zmieniając kompozycję lokalną LocalLayoutDirection
.
Jeśli ręcznie umieszczasz na ekranie kompozycje, element LayoutDirection
będzie
część LayoutScope
modyfikatora layout
lub elementu kompozycyjnego Layout
.
Jeśli używasz właściwości layoutDirection
, do tworzenia funkcji kompozycyjnych używaj funkcji place
. W przeciwieństwie do
placeRelative
metody place
nie zmienia się w zależności od kierunku układu
(od lewej do prawej lub od prawej do lewej).
Układy niestandardowe w akcji
Więcej informacji o układach i modyfikatorach znajdziesz w Podstawowe układy w funkcji tworzenia wiadomości, i zobacz, jak działają układy niestandardowe Utwórz przykładowe układy niestandardowe.
Więcej informacji
Więcej informacji o niestandardowych układach w sekcji Kompozycja znajdziesz w tych dodatkowych materiałach.
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Własne pomiary w układach tworzenia wiadomości
- Grafika w funkcji tworzenia wiadomości
- Tworzenie modyfikatorów