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 może mieć 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 dotyczące 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.
Rozmieszczanie każdego węzła w drzewie interfejsu jest procesem składającym się z 3 etapów. Każdy węzeł musi:
- Mierzenie elementów podrzędnych
- Decyduj o rozmiarze
- Umieść elementy podrzędne
Użycie zakresów określa, kiedy możesz mierzyć i umieszczać elementy podrzędne.
Układ można zmierzyć 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 mierzenia i układania elementu. Modyfikator przyjmuje funkcję lambda. Jej 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 służącą do umieszczania elementów opakowanych. W tym przypadku wysokość to wysokość elementuTextplusplaceableY, czylifirstBaselineToTopminus pierwsza linia bazowa elementuText. - Elementy opakowane umieszczasz na ekranie, wywołując
placeable.placeRelative(x, y). Jeśli elementy zawijane nie zostaną umieszczone, nie będą widoczne. W układzie od prawej do lewejplaceRelativeodzwierciedla pozycjęx; zobacz Kierunek układu. PozycjaytofirstBaselineToTopminus pierwsza linia bazowa tekstu, dzięki czemu pierwsza linia bazowa znajduje się w odległościfirstBaselineToTopod góry.
Aby sprawdzić, czy działa to 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 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 funkcję 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 } } } }
Komponenty podrzędne są ograniczone przez ograniczenia przychodzące Layout i są umieszczane na podstawie yPosition poprzedniej funkcji kompozycyjnej.
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 funkcje kompozycyjne na ekranie, LayoutDirection jest dostępny we właściwości layoutDirection elementu MeasureScope w modyfikatorze layout lub funkcji kompozycyjnej Layout.
Podczas korzystania z layoutDirection umieszczaj elementy kompozycyjne 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 układach niestandardowych w Compose.
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 funkcji Compose