ConstraintLayout
to układ, który umożliwia umieszczanie komponentów kompozycyjnych względem innych komponentów kompozycyjnych na ekranie. Jest to alternatywa dla używania wielu zagnieżdżonych elementów Row
, Column
, Box
i innych elementów układu niestandardowego. ConstraintLayout
przydaje się podczas wdrażania większych układów o bardziej skomplikowanych wymaganiach dotyczących wyrównania.
Używaj ConstraintLayout
w tych sytuacjach:
- Aby uniknąć zagnieżdżania wielu elementów
Column
iRow
w celu pozycjonowania elementów na ekranie i poprawić czytelność kodu. - Aby pozycjonować komponenty kompozycyjne względem innych komponentów kompozycyjnych lub pozycjonować komponenty kompozycyjne na podstawie wytycznych, barier lub łańcuchów.
W systemie View zalecanym sposobem tworzenia dużych i złożonych układów było używanie elementu ConstraintLayout
, ponieważ płaska hierarchia widoków zapewniała lepszą wydajność niż widoki zagnieżdżone. Nie jest to jednak problem w Compose, który może efektywnie obsługiwać głębokie hierarchie układów.
Rozpocznij korzystanie z usługi ConstraintLayout
Aby używać ConstraintLayout
w Compose, musisz dodać tę zależność w pliku build.gradle
(oprócz konfiguracji Compose):
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
ConstraintLayout
w Compose działa w ten sposób, korzystając z DSL:
- Utwórz odwołania do każdego elementu kompozycyjnego w
ConstraintLayout
za pomocącreateRefs()
lubcreateRefFor()
. - Ograniczenia są podawane za pomocą modyfikatora
constrainAs()
, który przyjmuje odwołanie jako parametr i umożliwia określenie jego ograniczeń w treści lambda. - Ograniczenia są określane za pomocą
linkTo()
lub innych przydatnych metod. parent
to istniejące odwołanie, którego można użyć do określenia ograniczeń w stosunku do samego elementu kompozycyjnegoConstraintLayout
.
Oto przykład funkcji kompozycyjnej korzystającej z funkcji ConstraintLayout
:
@Composable fun ConstraintLayoutContent() { ConstraintLayout { // Create references for the composables to constrain val (button, text) = createRefs() Button( onClick = { /* Do something */ }, // Assign reference "button" to the Button composable // and constrain it to the top of the ConstraintLayout modifier = Modifier.constrainAs(button) { top.linkTo(parent.top, margin = 16.dp) } ) { Text("Button") } // Assign reference "text" to the Text composable // and constrain it to the bottom of the Button composable Text( "Text", Modifier.constrainAs(text) { top.linkTo(button.bottom, margin = 16.dp) } ) } }
Ten kod ogranicza górną krawędź elementu Button
do elementu nadrzędnego z marginesem 16.dp
, a dolną krawędź elementu Button
do dolnej krawędzi elementu nadrzędnego również z marginesem 16.dp
.Text
Oddzielony interfejs API
W przykładzie ConstraintLayout
ograniczenia są określone w wierszu, a modyfikator znajduje się w funkcji kompozycyjnej, do której są stosowane. Czasami jednak lepiej jest oddzielić ograniczenia od układów, do których się odnoszą. Możesz na przykład zmienić ograniczenia na podstawie konfiguracji ekranu lub animować przejście między 2 zestawami ograniczeń.
W takich przypadkach możesz użyć symbolu ConstraintLayout
w inny sposób:
- Przekaż
ConstraintSet
jako parametr doConstraintLayout
. - Przypisz odwołania utworzone w
ConstraintSet
do funkcji kompozycyjnych za pomocą modyfikatoralayoutId
.
@Composable fun DecoupledConstraintLayout() { BoxWithConstraints { val constraints = if (minWidth < 600.dp) { decoupledConstraints(margin = 16.dp) // Portrait constraints } else { decoupledConstraints(margin = 32.dp) // Landscape constraints } ConstraintLayout(constraints) { Button( onClick = { /* Do something */ }, modifier = Modifier.layoutId("button") ) { Text("Button") } Text("Text", Modifier.layoutId("text")) } } } private fun decoupledConstraints(margin: Dp): ConstraintSet { return ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") constrain(button) { top.linkTo(parent.top, margin = margin) } constrain(text) { top.linkTo(button.bottom, margin) } } }
Gdy zechcesz zmienić ograniczenia, wystarczy, że przekażesz inne ConstraintSet
.
ConstraintLayout
pojęć
ConstraintLayout
zawiera koncepcje takie jak wytyczne, bariery i łańcuchy, które mogą pomóc w umieszczaniu elementów w kompozycji.
Wskazówki
Linie pomocnicze to niewielkie elementy wizualne, które ułatwiają projektowanie układów. Kompozycje można ograniczyć do linii pomocniczej. Wytyczne są przydatne do pozycjonowania elementów w określonym dp
lub percentage
w kompozycji nadrzędnej.
Istnieją 2 rodzaje linii pomocniczych: pionowe i poziome. Dwie poziome to top
i bottom
, a dwie pionowe to start
i end
.
ConstraintLayout { // Create guideline from the start of the parent at 10% the width of the Composable val startGuideline = createGuidelineFromStart(0.1f) // Create guideline from the end of the parent at 10% the width of the Composable val endGuideline = createGuidelineFromEnd(0.1f) // Create guideline from 16 dp from the top of the parent val topGuideline = createGuidelineFromTop(16.dp) // Create guideline from 16 dp from the bottom of the parent val bottomGuideline = createGuidelineFromBottom(16.dp) }
Aby utworzyć wytyczne, użyj polecenia createGuidelineFrom*
z wymaganym typem wytycznych. Spowoduje to utworzenie odwołania, którego można użyć w bloku Modifier.constrainAs()
.
Bariery
Barriers odwołują się do wielu komponentów kompozycyjnych, aby utworzyć wirtualną linię pomocniczą na podstawie najbardziej wysuniętego widżetu po określonej stronie.
Aby utworzyć barierę, użyj symbolu createTopBarrier()
(lub createBottomBarrier()
, createEndBarrier()
, createStartBarrier()
) i podaj odniesienia, które mają się na nią składać.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
Barierę można następnie wykorzystać w bloku Modifier.constrainAs()
.
Łańcuchy
Łańcuchy zapewniają zachowanie podobne do grup w przypadku jednej osi (poziomej lub pionowej). Drugą oś można ograniczyć niezależnie.
Aby utworzyć łańcuch, użyj createVerticalChain
lub createHorizontalChain
:
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val verticalChain = createVerticalChain(button, text, chainStyle = ChainStyle.Spread) val horizontalChain = createHorizontalChain(button, text) } }
Łańcuch można następnie wykorzystać w bloku Modifier.constrainAs()
.
Łańcuch można skonfigurować za pomocą różnych ChainStyles
, które określają sposób postępowania z przestrzenią otaczającą element kompozycyjny, np.:
ChainStyle.Spread
: przestrzeń jest równomiernie rozłożona na wszystkie komponenty, w tym wolną przestrzeń przed pierwszym komponentem i po ostatnim.ChainStyle.SpreadInside
: przestrzeń jest rozdzielana równomiernie między wszystkie komponenty kompozycyjne, bez wolnej przestrzeni przed pierwszym komponentem kompozycyjnym ani po ostatnim.ChainStyle.Packed
: przestrzeń jest rozdzielana przed pierwszym i po ostatnim komponencie, a komponenty są umieszczane obok siebie bez spacji między nimi.
Więcej informacji
Więcej informacji o ConstraintLayout
w Compose znajdziesz w sekcji Interfejsy API w działaniu w przykładach Compose, które używają ConstraintLayout
.
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony.
- Skupienie w trybie tworzenia
- Kotlin w Jetpack Compose
- Podstawy układu tworzenia