W Compose elementy interfejsu są reprezentowane przez funkcje kompozycyjne, które po wywołaniu emitują część interfejsu użytkownika, 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 i y) i rozmiar określony jako width
i height
.
Elementy nadrzędne definiują ograniczenia dla elementów podrzędnych. Dochodzi do zdefiniowania rozmiaru elementu
w ramach tych ograniczeń. Ograniczenia ograniczają minimalne i maksymalne wartości width
i height
elementu. Jeśli element ma elementy podrzędne, może mierzyć każdy element podrzędny, aby określić jego rozmiar. Gdy element określa i zgłasza własny rozmiar, można określić, jak względem niego rozmieszczać elementy podrzędne. Więcej informacji na ten temat znajdziesz w artykule Tworzenie układów niestandardowych.
Ułożenie każdego węzła w drzewie interfejsu obejmuje proces trzyetapowy. Każdy węzeł musi:
- Mierz wszystkie dzieci
- Określanie własnego rozmiaru
- Umieść elementy podrzędne
Użycie zakresów określa, kiedy możesz mierzyć i umieszczać dane dzieci.
Pomiar układu można wykonać tylko podczas przechodzenia pomiarów i procesów układu, a element podrzędny można umieścić tylko w ramach przebiegu układu (i po jego zmierzeniu). Ze względu na zakresy tworzenia wiadomości, takie jak MeasureScope
i PlacementScope
, jest to wymuszane podczas kompilacji.
Używanie modyfikatora układu
Aby zmienić sposób pomiaru i układu elementu, możesz użyć modyfikatora layout
. Funkcja Layout
jest funkcją lambda. Jej parametry obejmują element, który można zmierzyć, przekazany jako measurable
, oraz przychodzące ograniczenia elementu kompozycyjnego przekazywane jako constraints
. Niestandardowy modyfikator układu może wyglądać tak:
fun Modifier.customLayoutModifier() = layout { measurable, constraints -> // ... }
Wyświetlmy na ekranie znak Text
i ustawmy odległość od górnej krawędzi do punktu odniesienia. Właśnie tak działa modyfikator paddingFromBaseline
. Zastosowaliśmy go tutaj jako przykład.
Aby to zrobić, użyj modyfikatora layout
i ręcznie umieść funkcję kompozycyjną na ekranie. Oto oczekiwane działanie, w przypadku którego dopełnienie u góry Text
jest ustawione na 24.dp
:
Oto kod do utworzenia odstępów:
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 zawiera ten kod:
- W parametrze lambda
measurable
mierzysz wartośćText
reprezentowaną przez parametr wymierny, wywołując funkcjęmeasurable.measure(constraints)
. - Rozmiar funkcji kompozycyjnej określasz, wywołując metodę
layout(width, height)
, która zwraca też funkcję lambda służącą do umieszczania opakowanych elementów. W tym przypadku jest to wysokość między ostatnią bazą bazową a dodanym dopełnieniem u góry. - Aby umieścić opakowane elementy na ekranie, wywołaj
placeable.place(x, y)
. Jeśli opakowane elementy nie zostaną umieszczone, nie będą widoczne. Położeniey
odpowiada górnemu dopełnieniu, czyli pozycji pierwszej linii bazowej tekstu.
Aby sprawdzić, czy wszystko działa zgodnie z oczekiwaniami, użyj tego modyfikatora w elemencie 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 układów niestandardowych
Modyfikator layout
zmienia tylko funkcję wywoływania kompozycyjnego. Aby mierzyć i układać wiele elementów kompozycyjnych, użyj funkcji kompozycyjnej Layout
. Umożliwia on ręczne pomiary i rozmieszczanie dzieci. Wszystkie układy wyższego poziomu, takie jak Column
i Row
, korzystają z funkcji kompozycyjnej Layout
.
Stwórzmy podstawową wersję interfejsu Column
. Większość układów niestandardowych korzysta z tego wzoru:
@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 modyfikator layout
measurables
to lista elementów podrzędnych, które chcesz zmierzyć, a constraints
to ograniczenia z elementu nadrzędnego.
Zgodnie z tą samą logiką co wcześniej interfejs 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 } } } }
Podrzędne elementy kompozycyjne są ograniczone przez ograniczenia Layout
(bez ograniczeń minHeight
) i są umieszczane na podstawie funkcji yPosition
poprzedniej funkcji kompozycyjnej.
Oto jak można wykorzystać ten niestandardowy element kompozycyjny:
@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 funkcji kompozycyjnej, zmieniając lokalną kompozycję LocalLayoutDirection
.
Jeśli elementy kompozycyjne umieszczasz na ekranie ręcznie, element LayoutDirection
jest częścią elementu LayoutScope
modyfikatora layout
lub funkcji kompozycyjnej Layout
.
Jeśli używasz właściwości layoutDirection
, do tworzenia funkcji kompozycyjnych używaj funkcji place
. W przeciwieństwie do metody placeRelative
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 sekcji Podstawowe układy w narzędziu Compose. Działanie układów niestandardowych znajdziesz w artykule Tworzenie układów niestandardowych.
Więcej informacji
Więcej informacji o układach niestandardowych w funkcji tworzenia wiadomości znajdziesz w tych dodatkowych materiałach.
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Pomiary wewnętrzne w układach Compose
- Grafika w funkcji tworzenia wiadomości
- Modyfikatory tworzenia wiadomości