W Compose elementy interfejsu są reprezentowane przez funkcje kompozycyjne, które po wywołaniu emitują fragment interfejsu. Jest on następnie dodawany do drzewa interfejsu, które jest renderowane na ekranie. Każdy element interfejsu ma 1 element nadrzędny i potencjalnie wiele elementów podrzędnych. Każdy element znajduje się w elemencie nadrzędnym, określonym jako pozycja (x, y) i rozmiar, określony jako width
i height
.
Rodzice określają ograniczenia dla elementów podrzędnych. Element jest proszony o określenie swojego rozmiaru w ramach tych ograniczeń. Ograniczenia określają minimalną i maksymalną width
i height
elementu. Jeśli element ma elementy podrzędne, może zmierzyć każdy z nich, aby określić swój rozmiar. Gdy element określi i zgłosi swój rozmiar, może zdefiniować sposób umieszczania elementów podrzędnych względem siebie, co zostało szczegółowo opisane w artykule Tworzenie niestandardowych układów.
Układanie każdego węzła w drzewie interfejsu to proces trzyetapowy. Każdy węzeł musi:
- Mierzenie dowolnych elementów podrzędnych
- określać własny rozmiar,
- umieszczać elementy podrzędne,
Zakresy określają kiedy możesz mierzyć i umieszczać dzieci.
Pomiar układu można przeprowadzić tylko podczas pomiaru i przekazywania układu, a element podrzędny można umieścić tylko podczas przekazywania układu (i tylko po jego pomiarze). Ze względu na zakresy funkcji Compose, takie jak MeasureScope
i PlacementScope
, jest to egzekwowane w czasie kompilacji.
Używanie modyfikatora układu
Możesz użyć modyfikatora layout
, aby zmienić sposób pomiaru i układu elementu. Layout
to lambda. Jej parametry obejmują element, który możesz zmierzyć, przekazywany jako measurable
, oraz ograniczenia przychodzące tego komponentu, przekazywane jako constraints
. Modyfikator układu niestandardowego może wyglądać tak:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Wyświetlmy na ekranie znak Text
i określmy odległość od góry do linii bazowej pierwszego wiersza tekstu. Właśnie to robi modyfikator
paddingFromBaseline
. Używamy go tutaj jako przykładu.
Aby to zrobić, użyj modyfikatora layout
, aby ręcznie umieścić komponent na ekranie. Oto oczekiwane zachowanie, w którym ustawiono Text
górny odstęp 24.dp
:
Oto kod, który pozwala uzyskać taki odstęp:
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) } }
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 kompozycyjnego określa się przez wywołanie metody
layout(width, height)
, która udostępnia też wyrażenie lambda używane do umieszczania elementów opakowanych. W tym przypadku jest to wysokość między ostatnią linią bazową a dodanym dopełnieniem u góry. - Elementy opakowane umieszcza się na ekranie, wywołując funkcję
placeable.place(x, y)
. Jeśli zawinięte elementy nie zostaną umieszczone, nie będą widoczne.y
Pozycja odpowiada górnemu dopełnieniu – pozycji pierwszej linii bazowej tekstu.
Aby sprawdzić, czy działa on zgodnie z oczekiwaniami, użyj tego modyfikatora w przypadku 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 niestandardowych układów
Modyfikator layout
zmienia tylko funkcję kompozycyjną wywołania. Aby zmierzyć i ułożyć wiele komponentów, użyj komponentu Layout
. Ten komponent umożliwia ręczne mierzenie i układanie elementów podrzędnych. Wszystkie układy wyższego poziomu, takie jak Column
i Row
, są tworzone za pomocą komponentu Layout
.
Stwórzmy bardzo podstawową wersję Column
. Większość układów niestandardowych ma następujący wzorzec:
@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 zmierzyć, a constraints
to ograniczenia pochodzące od elementu nadrzędnego.
Zgodnie z tą samą logiką co wcześniej element MyBasicColumn
można zaimplementować 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 kompozycyjne podrzędne są ograniczone przez ograniczenia Layout
(bez ograniczeń minHeight
) i umieszczane na podstawie yPosition
poprzedniego elementu kompozycyjnego.
Oto jak można użyć tego 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 komponentu, zmieniając lokalną kompozycję LocalLayoutDirection
.
Jeśli umieszczasz funkcje kompozycyjne ręcznie na ekranie, LayoutDirection
jest częścią LayoutScope
modyfikatora layout
lub funkcji kompozycyjnej Layout
.
Podczas korzystania z funkcji layoutDirection
umieszczaj komponenty kompozycyjne za pomocą funkcji place
. W przeciwieństwie do metody
placeRelative
wartość 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 praktyce
Więcej informacji o układach i modyfikatorach znajdziesz w artykule Podstawowe układy w Compose. Przykłady niestandardowych układów znajdziesz w artykule Przykłady Compose, w których tworzone są niestandardowe układy.
Więcej informacji
Więcej informacji o układach niestandardowych w Compose znajdziesz w tych materiałach:
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Wymiary wewnętrzne w układach Compose
- Grafika w komponowaniu
- Tworzenie modyfikatorów