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 jeden 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, 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ć 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,
Użycie zakresów określa kiedy możesz mierzyć i umieszczać swoje 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 kompozycji, 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ć element kompozycyjny na ekranie. Oto wynikowe zachowanie, w którym górny margines wewnętrzny Text 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) } }
Oto 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 opakowanych elementów. 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. Pozycjayodpowiada 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)) } }
Text i wyświetlony w podglądzie.
Tworzenie niestandardowych układów
Modyfikator layout zmienia tylko komponent wywołujący. Aby zmierzyć i ułożyć 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 przykładowych aplikacjach Compose, które tworzą 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 język JavaScript jest wyłączony.
- Wymiary wewnętrzne w układach Compose
- Grafika w Compose
- Tworzenie modyfikatorów