ConstraintLayout
은 화면에 다른 컴포저블을 기준으로 컴포저블을 배치할 수 있는 레이아웃입니다. 여러 중첩된 Row
, Column
, Box
, 맞춤 레이아웃 요소 대신 사용할 수 있습니다. ConstraintLayout
은 더 복잡한 정렬 요구사항이 있는 더 큰 레이아웃을 구현할 때 유용합니다.
다음 시나리오에서는 ConstraintLayout
을 사용하는 것이 좋습니다.
- 코드 가독성 개선을 위해 화면에 요소를 배치하는 여러
Column
및Row
를 중첩하지 않습니다. - 다른 컴포저블을 기준으로 컴포저블을 배치하거나 가이드라인, 배리어, 체인을 기반으로 컴포저블을 배치합니다.
뷰 시스템에서 ConstraintLayout
은 크고 복잡한 레이아웃을 만드는 데 권장되는 방법이었습니다. 플랫 뷰 계층 구조가 중첩된 뷰보다 성능 면에서 더 좋았기 때문입니다. 그러나 이는 깊은 레이아웃 계층 구조를 효율적으로 처리할 수 있는 Compose에서는 문제가 되지 않습니다.
ConstraintLayout
시작하기
Compose에서 ConstraintLayout
을 사용하려면 build.gradle
에 이 종속 항목을 추가해야 합니다(Compose 설정에도).
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
Compose의 ConstraintLayout
은 DSL을 사용하여 다음과 같은 방식으로 작동합니다.
createRefs()
또는createRefFor()
를 사용하여ConstraintLayout
에서 각 컴포저블의 참조를 만듭니다.- 제약 조건은
constrainAs()
수정자를 사용하여 제공됩니다. 이 수정자는 참조를 매개변수로 사용하고 본문 람다에 제약 조건을 지정할 수 있게 합니다. - 제약 조건은
linkTo()
또는 다른 유용한 메서드를 사용하여 지정됩니다. parent
는ConstraintLayout
컴포저블 자체에 대한 제약 조건을 지정하는 데 사용할 수 있는 기존 참조입니다.
다음은 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) } ) } }
이 코드는 Button
의 상단을 여백이 16.dp
인 상위 요소로 제한하고 Text
를 여백이 16.dp
인 Button
의 하단으로 제한합니다.
분리된 API
ConstraintLayout
예에서 제약 조건은 적용되는 컴포저블의 수정자와 함께 인라인으로 지정됩니다. 그러나 제약 조건이 적용되는 레이아웃에서 제약 조건을 분리하는 것이 더 좋은 상황이 있습니다. 예를 들어 화면 구성을 기반으로 제약 조건을 변경하거나 두 제약 조건 세트 사이에 애니메이션을 적용할 수 있습니다.
이 같은 경우에는 ConstraintLayout
을 서로 다른 방식으로 사용할 수 있습니다.
ConstraintSet
을 매개변수로ConstraintLayout
에 전달합니다.layoutId
수정자를 사용하여ConstraintSet
에 생성된 참조를 컴포저블에 할당합니다.
@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) } } }
그러면 제약 조건을 변경해야 할 때 다른 ConstraintSet
을 전달하기만 하면 됩니다.
ConstraintLayout
개념
ConstraintLayout
에는 컴포저블 내에서 요소를 배치하는 데 도움이 될 수 있는 가이드라인, 배리어, 체인과 같은 개념이 포함되어 있습니다.
가이드라인
가이드라인은 레이아웃을 디자인할 때 사용할 수 있는 작은 시각적 도우미입니다. 컴포저블은 가이드라인으로 제한할 수 있습니다. 가이드라인은 상위 컴포저블 내에서 특정 dp
또는 percentage
에 요소를 배치하는 데 유용합니다.
가이드라인에는 세로, 가로 두 종류가 있습니다. 가로 가이드라인 두 개는 top
과 bottom
이고 세로 두 개는 start
와 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) }
가이드라인을 만들려면 필요한 가이드라인 유형과 함께 createGuidelineFrom*
을 사용합니다. 이렇게 하면 Modifier.constrainAs()
블록에서 사용할 수 있는 참조가 만들어집니다.
배리어
배리어는 여러 컴포저블을 참조하여, 지정된 쪽에서 가장 극단적인 위젯을 기반으로 가상 가이드라인을 만듭니다.
배리어를 만들려면 createTopBarrier()
(또는 createBottomBarrier()
, createEndBarrier()
, createStartBarrier()
)를 사용하고, 배리어를 구성해야 하는 참조를 제공합니다.
ConstraintLayout { val constraintSet = ConstraintSet { val button = createRefFor("button") val text = createRefFor("text") val topBarrier = createTopBarrier(button, text) } }
그러면 배리어를 Modifier.constrainAs()
블록에서 사용할 수 있습니다.
체인
체인은 단일 축(가로 또는 세로)에서 그룹과 같은 동작을 제공합니다. 다른 축은 독립적으로 제한할 수 있습니다.
체인을 만들려면 createVerticalChain
또는 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) } }
그러면 Modifier.constrainAs()
블록에서 체인을 사용할 수 있습니다.
체인은 여러 ChainStyles
로 구성하여 컴포저블을 둘러싼 공간을 처리하는 방법을 결정합니다. 예를 들면 다음과 같습니다.
ChainStyle.Spread
: 공간이 첫 번째 컴포저블 앞과 마지막 컴포저블 뒤의 여유 공간을 포함하여 모든 컴포저블에서 균등하게 분산됩니다.ChainStyle.SpreadInside
: 공간이 첫 번째 컴포저블 앞이나 마지막 컴포저블 뒤의 여유 공간 없이 모든 컴포저블에서 균등하게 분산됩니다.ChainStyle.Packed
: 공간이 첫 번째 컴포저블 앞과 마지막 컴포저블 뒤에 분산되고 컴포저블은 서로 간에 공간 없이 패킹됩니다.
자세히 알아보기
ConstraintLayout
를 사용하는 Compose 샘플의 작동 중인 API에서 Compose의 ConstraintLayout
에 관해 자세히 알아보세요.
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- Compose의 포커스
- Jetpack Compose용 Kotlin
- Compose 레이아웃 기본사항