Наборы ограничений ConstraintSet

Последнее обновление: 07.04.2024

В предыдущих статьях все ограничения определялись внутри модификаторов, применяемых к отдельным компонентам. Но Jetpack Compose также позволяет объявлять ограничения отдельно в виде объекта ConstraintSet. Подобный набор ограничений затем можно передать в ConstraintLayout и применить к компонентам. Кроме того, создаваемые ограничения можно использовать повторно без необходимости дублировать объявления модификаторов. Это также обеспечивает гибкость при передачи различных наборов ограничений в зависимости от различных критериев. Например, контейнер может использовать разные наборы ограничений в зависимости от размера экрана или ориентации устройства.

Рассмотрим небольшой пример:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.compose.ui.unit.Dp
import androidx.constraintlayout.compose.ConstraintSet

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent{
            val constraints = myConstraintSet(margin = 8.dp)
            ConstraintLayout(constraints, Modifier.fillMaxSize()) {
                Box(Modifier.size(200.dp).background(Color.DarkGray).layoutId("box1"))
            }
        }
    }
}
private fun myConstraintSet(margin: Dp): ConstraintSet {
    return ConstraintSet {
        val box1 = createRefFor("box1")
        constrain(box1) {
            linkTo(parent.top, parent.bottom, topMargin = margin, bottomMargin = margin)
            linkTo(parent.start, parent.end, startMargin = margin, endMargin = margin)
        }
    }
}

Прежде всего здесь определена функция myConstraintSet, которая принимает значение отступов и возвращает объект ConstraintSet:

private fun myConstraintSet(margin: Dp): ConstraintSet {
    return ConstraintSet {

Передача отступов позволяет сделать более гибкой настройку отступов в ограничениях, хотя это в принципе необязательно.

В функции ConstraintSet выполняется вызов функции createRefFor() для создания ссылки на любой компонуемый объект, к которому применяется набор ограничений. Причем в данном случае компонент будет иметь идентификатор "box1":

val box1 = createRefFor("box1")

Затем путем вызова функции constrain() создается набор ограничений. В эту функцию передается ссылка на компонент и далее в ней определяются ограничения.

constrain(box1) {
    linkTo(parent.top, parent.bottom, topMargin = margin, bottomMargin = margin)
    linkTo(parent.start, parent.end, startMargin = margin, endMargin = margin)
}

Создав набор ограничений, его можно передать в ConstraintLayout и применить к компонентам. Это включает в себя создание объекта ConstraintSet и его передачу его в ConstraintLayout:

val constraints = myConstraintSet(margin = 8.dp)
    ConstraintLayout(constraints, Modifier.fillMaxSize()) {

Для связывания ссылки на набор ограничений с компонентом применяется функции-модификатор layoutId(), в которую передается идентификатор компонента, к которому применяются ограничения:

Box(Modifier.size(200.dp).background(Color.DarkGray).layoutId("box1"))

Обратите внимание, что здесь передается тот же идентификатор "box1", для которого устанавливались ограничения в ConstraintSet.

ConstraintLayout и набор ограничений в Jetpack Compose на Kotlin на Android

Аналогичным образом можно задавать ограничения в наборе для нескольких компонентов:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.ConstraintSet

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent{
            val constraints = myConstraintSet()
            ConstraintLayout(constraints, Modifier.fillMaxSize()) {
                Box(Modifier.size(200.dp).background(Color.DarkGray).layoutId("box1"))
                Box(Modifier.size(200.dp).background(Color.Red).layoutId("box2"))
            }
        }
    }
}
private fun myConstraintSet(): ConstraintSet {
    return ConstraintSet {
        val box1 = createRefFor("box1")
        val box2 = createRefFor("box2")
        constrain(box1) {
            centerHorizontallyTo(parent)
            top.linkTo(parent.top)
            bottom.linkTo(box2.top)
        }
        constrain(box2) {
            centerHorizontallyTo(parent)
            top.linkTo(box1.bottom)
            bottom.linkTo(parent.bottom)
        }
    }
}

Теперь в функции myConstraintSet создаются две ссылки - box1 и box2, и для каждой из них создаются ограничения. Причем мы можем использовать эти ссылки для взаимной установки ограничений относительно друг друга.

ConstraintLayout и ConstraintSet в Jetpack Compose на Kotlin на Android
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850