ConstraintLayout
ist ein Layout, mit dem Sie Composables relativ zu anderen Composables auf dem Bildschirm platzieren können. Es ist eine Alternative zur Verwendung mehrerer verschachtelter Row
-, Column
-, Box
- und anderer benutzerdefinierter Layout-Elemente. ConstraintLayout
ist nützlich, wenn Sie größere Layouts mit komplexeren Ausrichtungsanforderungen implementieren.
In den folgenden Szenarien kann es sinnvoll sein, ConstraintLayout
zu verwenden:
- Um die Lesbarkeit des Codes zu verbessern, sollten Sie nicht mehrere
Column
- undRow
-Tags verschachteln, um Elemente auf dem Bildschirm zu positionieren. - Sie können Composables relativ zu anderen Composables oder basierend auf Richtlinien, Barrieren oder Ketten positionieren.
Im View-System war ConstraintLayout
die empfohlene Methode zum Erstellen großer und komplexer Layouts, da eine flache View-Hierarchie besser für die Leistung war als verschachtelte Views. In Compose ist das jedoch kein Problem, da hier auch tiefe Layoutstrukturen effizient verarbeitet werden können.
Mit ConstraintLayout
beginnen
Wenn Sie ConstraintLayout
in Compose verwenden möchten, müssen Sie diese Abhängigkeit in Ihrer build.gradle
hinzufügen (zusätzlich zur Compose-Einrichtung):
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
ConstraintLayout
in Compose funktioniert so:
- Erstellen Sie mit
createRefs()
odercreateRefFor()
Referenzen für jede Composable inConstraintLayout
. - Einschränkungen werden mit dem Modifikator
constrainAs()
angegeben, der die Referenz als Parameter verwendet und mit dem Sie die Einschränkungen im Lambda-Ausdruck des Texts angeben können. - Einschränkungen werden mit
linkTo()
oder anderen hilfreichen Methoden angegeben. parent
ist eine vorhandene Referenz, mit der Einschränkungen für das zusammensetzbare ElementConstraintLayout
angegeben werden können.
Hier ein Beispiel für eine zusammensetzbare Funktion, die eine ConstraintLayout
verwendet:
@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) } ) } }
Dieser Code schränkt die Oberkante von Button
auf das übergeordnete Element mit einem Rand von 16.dp
und die Unterkante von Button
ebenfalls mit einem Rand von 16.dp
ein.Text
Entkoppelte API
Im Beispiel ConstraintLayout
werden Einschränkungen inline mit einem Modifier im Composable angegeben, auf das sie angewendet werden. Es gibt jedoch Situationen, in denen es besser ist, die Einschränkungen von den Layouts zu entkoppeln, auf die sie angewendet werden. Sie können beispielsweise die Einschränkungen basierend auf der Bildschirmkonfiguration ändern oder zwischen zwei Einschränkungssätzen animieren.
In solchen Fällen können Sie ConstraintLayout
auf andere Weise verwenden:
- Übergeben Sie ein
ConstraintSet
als Parameter anConstraintLayout
. - Weisen Sie Composables mit dem Modifier
layoutId
Referenzen zu, die inConstraintSet
erstellt wurden.
@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) } } }
Wenn Sie die Einschränkungen ändern müssen, können Sie einfach ein anderes ConstraintSet
übergeben.
ConstraintLayout
-Konzepte
ConstraintLayout
enthält Konzepte wie Richtlinien, Barrieren und Ketten, die beim Positionieren von Elementen in Ihrem Composable helfen können.
Richtlinien
Richtlinien sind kleine visuelle Hilfsmittel, mit denen sich Layouts gestalten lassen. Composables können an eine Richtlinie gebunden werden. Mit Richtlinien lassen sich Elemente an einer bestimmten dp
oder percentage
innerhalb der übergeordneten Composable-Funktion positionieren.
Es gibt zwei verschiedene Arten von Hilfslinien: vertikale und horizontale. Die beiden horizontalen sind top
und bottom
und die beiden vertikalen start
und 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) }
Verwenden Sie createGuidelineFrom*
, um eine Richtlinie zu erstellen. Geben Sie dabei den erforderlichen Richtlinientyp an. Dadurch wird eine Referenz erstellt, die im Modifier.constrainAs()
-Block verwendet werden kann.
Barrieren
Barriers verweisen auf mehrere Composables, um eine virtuelle Richtlinie basierend auf dem äußersten Widget auf der angegebenen Seite zu erstellen.
Verwenden Sie zum Erstellen einer Barriere createTopBarrier()
(oder createBottomBarrier()
, createEndBarrier()
, createStartBarrier()
) und geben Sie die Referenzen an, aus denen die Barriere bestehen soll.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
Die Barriere kann dann in einem Modifier.constrainAs()
-Block verwendet werden.
Chains
Ketten bieten gruppenähnliches Verhalten auf einer einzelnen Achse (horizontal oder vertikal). Die andere Achse kann unabhängig eingeschränkt werden.
Verwenden Sie zum Erstellen einer Kette entweder createVerticalChain
oder 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) } }
Die Kette kann dann im Modifier.constrainAs()
-Block verwendet werden.
Eine Kette kann mit verschiedenen ChainStyles
konfiguriert werden, die festlegen, wie mit dem Leerraum um eine zusammensetzbare Funktion umgegangen werden soll, z. B.:
ChainStyle.Spread
: Der Leerraum wird gleichmäßig auf alle Composables verteilt, einschließlich des Leerraums vor dem ersten und nach dem letzten Composable.ChainStyle.SpreadInside
: Der Platz wird gleichmäßig auf alle Composables verteilt, ohne dass vor dem ersten oder nach dem letzten Composable kostenloser Platz vorhanden ist.ChainStyle.Packed
: Der Leerraum wird vor dem ersten und nach dem letzten Composable verteilt. Die Composables werden ohne Leerraum dazwischen zusammengefasst.
Weitere Informationen
Compose-Beispiele, in denen ConstraintLayout
verwendet wirdConstraintLayout
Empfehlungen für dich
- Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Fokus in Compose
- Kotlin für Jetpack Compose
- Grundlagen des Compose-Layouts