W Compose elementy interfejsu są reprezentowane przez funkcje typu „composable”, które po wywołaniu emitują fragment interfejsu, który jest następnie dodawany 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, określony jako width i height.
Rodzice definiują ograniczenia dla elementów podrzędnych. Element musi określić swój rozmiar
w ramach tych ograniczeń. Ograniczenia określają minimalną i maksymalną wartość 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, jak opisano szczegółowo w artykule Tworzenie układów niestandardowych.
Układanie każdego węzła w drzewie interfejsu to proces składający się z 3 kroków. Każdy węzeł musi:
- Mierzenie elementów podrzędnych
- samodzielnie określać swój rozmiar,
- Umieść elementy podrzędne
Użycie zakresów określa, kiedy możesz mierzyć i umieszczać elementy podrzędne.
Układ można mierzyć tylko podczas etapów pomiaru i układu, a element podrzędny można umieścić tylko podczas etapów układu (i tylko po jego zmierzeniu). Ze względu na zakresy Compose, takie jak MeasureScope i PlacementScope, jest to wymuszane 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, której parametry obejmują element, który można zmierzyć, przekazywany jako measurable, oraz ograniczenia przychodzące tego elementu kompozycyjnego, przekazywane jako constraints. Modyfikator układu niestandardowego może wyglądać tak:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Wyświetl Text na ekranie i kontroluj odległość od góry do linii bazowej pierwszego wiersza tekstu. Dokładnie to robi modyfikator paddingFromBaseline. Tutaj implementujesz go jako przykład.
Aby to zrobić, użyj modyfikatora layout, aby ręcznie umieścić element kompozycyjny na ekranie. Oto wynik, gdy dopełnienie górne Text jest ustawione na 24.dp:
paddingFromBaseline.
Oto kod, który pozwala uzyskać 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
measurablemierzyszTextreprezentowany przez mierzalny parametr, wywołującmeasurable.measure(constraints). - Rozmiar elementu kompozycyjnego określasz, wywołując metodę
layout(width, height), która udostępnia też funkcję lambda używaną do umieszczania elementów opakowanych. W tym przypadku jest to wysokość między ostatnią linią bazową a dodanym górnym dopełnieniem. - Elementy opakowane umieszczasz na ekranie, wywołując funkcję
placeable.place(x, y). Jeśli elementy zawijane nie zostaną umieszczone, nie będą widoczne. Pozycjayodpowiada górnemu dopełnieniu: pozycji pierwszej linii bazowej tekstu.
Aby sprawdzić, czy działa to zgodnie z oczekiwaniami, użyj tego modyfikatora w 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 układów niestandardowych
Modyfikator layout zmienia tylko wywołujący element kompozycyjny. Aby zmierzyć i rozmieścić wiele funkcji kompozycyjnych, użyj funkcji kompozycyjnej Layout. Ten element kompozycyjny 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ą funkcji kompozycyjnej Layout.
W tym przykładzie tworzymy bardzo podstawową wersję Column. Większość układów niestandardowych ma taki 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 z elementu nadrzędnego.
Zgodnie z tą samą logiką co wcześniej 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 są umieszczane na podstawie yPosition poprzedniego elementu kompozycyjnego.
Oto jak można użyć tego niestandardowego elementu kompozycyjnego:
@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 elementu kompozycyjnego, zmieniając kompozycję lokalną LocalLayoutDirection.
Jeśli ręcznie umieszczasz elementy kompozycyjne na ekranie, LayoutDirection jest częścią LayoutScope modyfikatora layout lub elementu kompozycyjnego Layout.
Podczas korzystania z layoutDirection umieszczaj komponenty za pomocą place. W przeciwieństwie do metody placeRelative właściwość 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 kodach Compose, które tworzą niestandardowe układy.
Więcej informacji
Więcej informacji o niestandardowych układach w Compose znajdziesz w tych materiałach:
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy język JavaScript jest wyłączony.
- Pomiary wewnętrzne w układach Compose
- Grafika w Compose
- Modyfikatory tworzenia