W Compose elementy interfejsu są reprezentowane przez funkcje kompozycyjne, które po wywołaniu emitują fragment interfejsu, a następnie są dodawane do drzewa interfejsu renderowanego na ekranie. Każdy element interfejsu ma 1 element nadrzędny i potencjalnie wiele elementów podrzędnych. Każdy element znajduje się też w elemencie nadrzędnym, określonym jako pozycja (x, y) i rozmiar, podany 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ć jego 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:
- Mierz wszystkie elementy podrzędne
- 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świetl Text na ekranie i określ odległość od góry do linii bazowej pierwszego wiersza tekstu. Właśnie to robi modyfikator paddingFromBaseline. W tym przykładzie implementujesz go.
Aby to zrobić, użyj modyfikatora layout, aby ręcznie umieścić komponent na ekranie. Oto wynikowe zachowanie, w którym Text górny odstęp wewnętrzny jest ustawiony na 24.dp:
paddingFromBaseline.
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
measurablemierzysz wartośćTextreprezentowaną 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. Położenieyodpowiada górnemu dopełnieniu: położeniu 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)) } }
Text i wyświetlony w podglądzie.
Tworzenie niestandardowych układów
Modyfikator layout zmienia tylko funkcję kompozycyjną wywołania. Aby zmierzyć i rozmieścić wiele komponentów, użyj komponentu Layout. Ten komponent umożliwia ręczne pomiary i układanie elementów podrzędnych. Wszystkie układy wyższego poziomu, takie jak Column i Row, są tworzone za pomocą komponentu Layout.
Ten przykład tworzy 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!") } }
Column.
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 layoutDirection umieszczaj komponenty 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