ConstraintLayout è un layout che ti consente di posizionare i composable rispetto
ad altri composable sullo schermo. È un'alternativa all'utilizzo di più elementi di layout personalizzati Row, Column, Box e altri nidificati. ConstraintLayout
è utile quando implementi layout più grandi con requisiti di allineamento più complessi.
Prendi in considerazione l'utilizzo di ConstraintLayout nei seguenti scenari:
- Per evitare di nidificare più
ColumneRowper posizionare gli elementi sullo schermo e migliorare la leggibilità del codice. - Per posizionare i composable rispetto ad altri composable o in base a linee guida, barriere o catene.
Nel sistema View, ConstraintLayout era il modo consigliato per creare layout grandi e complessi, in quanto una gerarchia di visualizzazione piatta era migliore per il rendimento rispetto alle visualizzazioni nidificate. Tuttavia, questo non è un problema in Compose, che è in grado di
gestire in modo efficiente gerarchie di layout complesse.
Inizia a utilizzare ConstraintLayout
Per utilizzare ConstraintLayout in Compose, devi aggiungere questa dipendenza in
build.gradle (oltre alla
configurazione di Compose):
implementation "androidx.constraintlayout:constraintlayout-compose:$constraintlayout_compose_version"
ConstraintLayout in Scrittura Magica funziona nel seguente modo utilizzando un
DSL:
- Crea riferimenti per ogni componibile in
ConstraintLayoututilizzandocreateRefs()ocreateRefFor(). - I vincoli vengono forniti utilizzando il modificatore
constrainAs(), che accetta il riferimento come parametro e consente di specificarne i vincoli nel corpo della lambda. - I vincoli vengono specificati utilizzando
linkTo()o altri metodi utili. parentè un riferimento esistente che può essere utilizzato per specificare i vincoli relativi al componibileConstraintLayoutstesso.
Ecco un esempio di composable che utilizza un 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) } ) } }
Questo codice vincola la parte superiore di Button all'elemento padre con un margine di
16.dp e un Text alla parte inferiore di Button, anch'esso con un margine di
16.dp.
Button e un Text componibili vincolati tra loro in un
ConstraintLayout.
API disaccoppiata
Nell'esempio ConstraintLayout,
i vincoli vengono specificati inline, con un modificatore nel componibile a cui
vengono applicati. Tuttavia, in alcune situazioni è preferibile separare i vincoli dai layout a cui si applicano. Ad esempio, potresti voler
modificare i vincoli in base alla configurazione dello schermo o animare due
set di vincoli.
Per casi come questi, puoi utilizzare ConstraintLayout in un altro modo:
- Trasmetti un
ConstraintSetcome parametro aConstraintLayout. - Assegna i riferimenti creati in
ConstraintSetai componibili utilizzando il modificatorelayoutId.
@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) } } }
Poi, quando devi modificare i vincoli, puoi semplicemente passare un ConstraintSet diverso.
ConstraintLayout concetti
ConstraintLayout contiene concetti come linee guida, barriere e catene
che possono aiutarti a posizionare gli elementi all'interno del tuo componente.
Linee guida
Le guide sono piccoli aiuti visivi per progettare i layout. I composable possono essere
vincolati a una linea guida. Le guide sono utili per posizionare gli elementi a una
determinata dp o percentage all'interno del composable principale.
Esistono due tipi diversi di linee guida: verticali e orizzontali. Le
due orizzontali sono top e bottom, mentre le due verticali sono start e
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) }
Per creare una linea guida, utilizza createGuidelineFrom* con il tipo di linea guida
richiesto. In questo modo viene creato un riferimento che può essere utilizzato nel blocco Modifier.constrainAs().
Barriere
Barriere fa riferimento a più componenti combinabili per creare una linea guida virtuale basata sul widget più estremo sul lato specificato.
Per creare una barriera, utilizza createTopBarrier() (o: createBottomBarrier(),
createEndBarrier(), createStartBarrier()) e fornisci i riferimenti che
devono costituire la barriera.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
La barriera può quindi essere utilizzata in un blocco Modifier.constrainAs().
Catene
Le catene forniscono un comportamento simile a quello dei gruppi in un singolo asse (orizzontalmente o verticalmente). L'altro asse può essere vincolato in modo indipendente.
Per creare una catena, utilizza createVerticalChain o
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) } }
La catena può quindi essere utilizzata nel blocco Modifier.constrainAs().
Una catena può essere configurata con diversi ChainStyles, che decidono come
gestire lo spazio che circonda un componente, ad esempio:
ChainStyle.Spread: lo spazio è distribuito uniformemente tra tutti i componenti, incluso lo spazio libero prima del primo componente e dopo l'ultimo componente.ChainStyle.SpreadInside: lo spazio è distribuito uniformemente tra tutti i composable, senza spazio libero prima del primo composable o dopo l'ultimo composable.ChainStyle.Packed: lo spazio viene distribuito prima del primo e dopo l'ultimo elemento componibile, che vengono raggruppati senza spazio tra l'uno e l'altro.
Scopri di più
Scopri di più su ConstraintLayout in Compose dagli esempi di API in azione negli
esempi di Compose che utilizzano ConstraintLayout.