W Compose elementy interfejsu są reprezentowane przez funkcje kompozycyjne, które po wywołaniu emitują część interfejsu użytkownika, który jest następnie dodawany do drzewa interfejsu renderowanego 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:
- Pomiar elementów podrzędnych
- określać własny rozmiar,
- umieszczać swoje elementy podrzędne.
Zastosowanie zakresów określa, kiedy możesz mierzyć i umieszczać dzieci.
Pomiar układu można przeprowadzić tylko podczas przechodzenia pomiarów i procesów układu, a element podrzędny można umieścić tylko w ramach przebiegu układu (i po jego zmierzeniu). Ze względu na zakresy tworzenia wiadomości, takie jak MeasureScope
i PlacementScope
, jest to wymuszane podczas kompilacji.
Używanie modyfikatora układu
Za pomocą modyfikatora layout
możesz zmienić sposób pomiaru i układania elementu. Funkcja Layout
jest funkcją lambda. Jej parametry obejmują element, który można zmierzyć, przekazany jako measurable
, oraz przychodzące ograniczenia elementu kompozycyjnego przekazywane jako constraints
. Niestandardowy modyfikator układu może wyglądać tak:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Wyświetlmy na ekranie znak Text
i ustawmy odległość od górnej krawędzi do punktu odniesienia. Właśnie tak działa modyfikator paddingFromBaseline
. Zastosowaliśmy go tutaj jako przykład.
Aby to zrobić, użyj modyfikatora layout
, aby ręcznie umieścić komponent na ekranie. 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 rozmieszczenie:
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 dzieje się w tym kodzie:
- W parametrze lambda
measurable
mierzysz wartośćText
reprezentowaną przez parametr do pomiaru, wywołując funkcjęmeasurable.measure(constraints)
. - Rozmiar funkcji kompozycyjnej określasz, wywołując metodę
layout(width, height)
, która zwraca też funkcję lambda służącą do umieszczania opakowanych elementów. W tym przypadku jest to wysokość między ostatnią linią bazową a dodaną górną przestrzenią. - Aby umieścić opakowane elementy na ekranie, wywołaj
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 przypadku tagu 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 wywoływane składane. Aby mierzyć i układać wiele elementów kompozycyjnych, użyj funkcji kompozycyjnej Layout
. Umożliwia on ręczne pomiary i rozmieszczanie dzieci. 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 wzór:
@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 w przypadku modyfikatora layout
, measurables
to lista elementów podrzędnych, które należy mierzyć, 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 } } } }
Elementy składowe podrzędne są ograniczone przez ograniczenia Layout
(bez ograniczeń minHeight
) i są umieszczane na podstawie yPosition
poprzedniego elementu składowego.
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 funkcje kompozycyjne umieszczasz ręcznie na ekranie, LayoutDirection
jest częścią LayoutScope
modyfikatora layout
lub funkcji kompozycyjnej Layout
.
Podczas korzystania z funkcji layoutDirection
umieszczaj komponenty za pomocą elementu place
. W przeciwieństwie do metody placeRelative
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 artykule Układy podstawowe w Compose, a o niestandardowych układach dowiesz się więcej z artykułu Przykłady tworzenia niestandardowych układów w Compose.
Więcej informacji
Więcej informacji o niestandardowych układach w edytorze kompozycji znajdziesz w tych dodatkowych materiałach.
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Pomiary wewnętrzne w układach Compose
- Grafika w Compose
- Tworzenie modyfikatorów