Layout vincolo in Scrivi

ConstraintLayout è un layout che ti consente di posizionare i composabili rispetto ad altri composabili sullo schermo. È un'alternativa all'utilizzo di più elementi personalizzati di layout Row, Column, Box e altri elementi di layout personalizzati nidificati. ConstraintLayout è utile per implementare layout più grandi con requisiti di allineamento più complicati.

Valuta la possibilità di utilizzare ConstraintLayout nei seguenti scenari:

  • Per evitare di nidificare più Column e Row per posizionare gli elementi sullo schermo, migliora la leggibilità del codice.
  • Per posizionare i composabili rispetto ad altri composabili o per posizionare i composabili in base a linee guida, barriere o catene.

Nel sistema di visualizzazione, ConstraintLayout era il metodo consigliato per creare layout grandi e complessi, in quanto una gerarchia di visualizzazioni 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:1.0.1"

ConstraintLayout in Scrittura funziona nel seguente modo utilizzando un DSL:

  • Crea riferimenti per ogni composable in ConstraintLayout utilizzando createRefs() o createRefFor()
  • I vincoli vengono forniti utilizzando il modificatore constrainAs(), che prende il riferimento come parametro e ti consente di specificare i relativi vincoli nel corpo della funzione lambda.
  • I vincoli vengono specificati utilizzando linkTo() o altri metodi utili.
  • parent è un riferimento esistente che può essere utilizzato per specificare vincoli nei confronti del componibile ConstraintLayout stesso.

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 principale con un margine di 16.dp e un Text alla parte inferiore di Button, sempre con un margine di 16.dp.

Mostra un pulsante e un elemento di testo disposti in un layout vincolato

API disaccoppiata

Nell'esempio ConstraintLayout, i vincoli sono specificati in linea, con un modificatore nel composable a cui vengono applicati. Tuttavia, in alcune situazioni è preferibile disaccoppiare i vincoli dai layout a cui si applicano. Ad esempio, potresti voler cambiare i vincoli in base alla configurazione dello schermo o animare tra due insiemi di vincoli.

Per casi come questi, puoi utilizzare ConstraintLayout in un modo diverso:

  1. Passa un ConstraintSet come parametro a ConstraintLayout.
  2. Assegna i riferimenti creati in ConstraintSet ai composabili utilizzando il modificatore layoutId.

@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 le limitazioni, puoi semplicemente passare un valore ConstraintSet diverso.

Concetti di ConstraintLayout

ConstraintLayout contiene concetti come linee guida, barriere e catene che possono aiutarti a posizionare gli elementi all'interno del tuo Composable.

Linee guida

Le linee guida sono piccoli ausili visivi per progettare i layout. I composabili possono essere vincolati a una linea guida. Le linee guida sono utili per posizionare gli elementi in un determinato dp o percentage all'interno del composable principale.

Esistono due tipi diversi di linee guida, verticali e orizzontali. Le due linee 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. Viene creato un riferimento che può essere utilizzato nel blocco Modifier.constrainAs().

Barriere

Barriere fa riferimento a più composabili per creare una linea guida virtuale in base al widget più estremo sul lato specificato.

Per creare una barriera, utilizza createTopBarrier() (o createBottomBarrier(), createEndBarrier(), createStartBarrier()) e fornisci i riferimenti che devono costituirla.

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 di un gruppo in un singolo asse (orizzontale o verticale). 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 determinano come gestire lo spazio che circonda un composable, ad esempio:

  • ChainStyle.Spread: lo spazio viene distribuito in modo uniforme tra tutti i composabili, incluso lo spazio libero prima del primo composable e dopo l'ultimo composable.
  • ChainStyle.SpreadInside: lo spazio viene distribuito in modo uniforme tra tutti i composabili, senza spazi vuoti prima del primo composable o dopo l'ultimo.
  • ChainStyle.Packed: lo spazio viene distribuito prima del primo e dopo l'ultimo composable, i composable sono raggruppati senza spazi tra loro.

Scopri di più

Scopri di più su ConstraintLayout in Compose dalle API in azione nei campioni di Compose che utilizzano ConstraintLayout.

Nessun suggerimento al momento.

Prova ad al tuo Account Google.