Android
Android) Compose의 ConstraintLayout
가짜 개발자
2022. 6. 1. 19:35
기존의 안드로이드에서 레이아웃의 중첩된 계층 구조의 성능을 개선하기 위해 ConstaintLayout을 사용했습니다.
Compose에서는 measure를 한 번만 하기 때문에 ConstraintLayout의 성능상 이점이 필요 없습니다.
다만, 개인적으로 뷰를 짜게 될 때 여전히 ConstraintLayout이 편하다는 생각이 들었습니다.
build.gradle
- 주의 사항으로 Compose의 버전과 Compose-ConstrainLayout의 버전이 다릅니다.
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02"
Compose-ConstrainLayout
- Compose-ConstratinLayout은 Kotlin DSL(Domain Specific Language)와 함께 작동합니다.
- ID를 생성하여 이를 참조하여 뷰의 배치를 구성할 수 있습니다.
- Modifier의 constraintAs()를 사용하여 생성한 ID를 Compose로 사용할 수 있습니다.
- ID를 하나를 생성하려면 createRef()로 생성합니다. 여러 ID를 생성하려면 createRefs()로 생성합니다.
- 기존의 ContsraintLayout의 app:layout_constraintTop_toTopOf 처럼 뷰들의 ID를 참조하여 연결하는 방식을 Compose-ConstraintLayout에서 linkTo를 통해 사용합니다.
@Composable
fun ConstraintLayoutContent() {
ConstraintLayout {
// 참조할 ID 생성.
val (button, text) = createRefs()
Button(
onClick = { /* Do something */ },
modifier = Modifier.constrainAs(button) {
// linkTo를 통해 button의 top을 parent의 top에 오게한다.
// parent의 top을 기준으로 16.dp 마진
top.linkTo(parent.top, margin = 16.dp)
}
) {
Text("Button")
}
Text("Text", Modifier.constrainAs(text) {
// text의 top을 button의 bottom에 오게 한다.
// button의 bottom을 기준으로 16.dp 마진
top.linkTo(button.bottom, margin = 16.dp)
})
}
}
- Text를 중앙에 배치하려면, centerHorizontallyTo를 사용합니다.
- 다만, Text를 centerHorizontallyTo를 parent로 줬는데, Button 기준으로 중앙에 배치된 것처럼 보입니다.
- 이는 자식 Composables를 표현할 수 있는 최소한의 크기만을 사용하기 때문입니다.
- 전체 화면으로 확장해서 사용하려면 Modifier의 fillMaxSize, size 등을 사용하면 됩니다.
@Composable
fun ConstraintLayoutContent() {
ConstraintLayout {
...
Text("Text", Modifier.constrainAs(text) {
top.linkTo(button.bottom, margin = 16.dp)
centerHorizontallyTo(parent)
})
}
}
분리된 API
- 화면 구성에 따라 다르게 ConstraintLayout을 구성할 때 이를 분리시켜 사용할 수 있습니다.
- ConstraintSet을 ConstraintLayout 생성 시 파라미터로 전달합니다.
- ConstraintLayout에서는 ConstraintSet에서 정의해놓은 구성에서 ID만 입력해 사용할 수 있습니다.
@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)
}
}
}
반응형