반응형
SubcomposeLayout란?
SubcomposeLayout은 Jetpack Compose에서 제공하는 고급 레이아웃 API로, 레이아웃의 일부 요소를 먼저 측정하고, 이 정보를 바탕으로 다른 요소를 측정하거나 배치할 수 있도록 설계된 커스텀 레이아웃입니다.
보통 Compose의 레이아웃은 모든 자식 요소를 동시에 측정하고 배치합니다. 하지만 **SubcomposeLayout**은 이런 일반적인 흐름을 벗어나 순차적인 측정 및 배치가 필요한 복잡한 레이아웃에 적합합니다.
왜 SubcomposeLayout이 필요한가?
- 순차적인 측정
일부 요소의 크기나 배치 정보가 다른 요소를 측정하거나 배치하는 데 필요할 때. - 동적 레이아웃
예를 들어, 특정 UI 요소의 크기를 기반으로 다른 요소를 배치해야 하는 경우. - 레이아웃 최적화
특정 요소를 조건부로 렌더링하거나, 필요한 요소만 측정/배치하여 성능을 최적화할 수 있음.
사용법
SubcomposeLayout은 기본적으로 다음 단계를 따릅니다:
- subcompose: 특정 키로 자식 컴포저블을 정의.
- measure: 자식의 크기를 측정.
- layout: 부모 레이아웃의 크기를 정의하고 자식을 배치.
기본 코드 예제
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.unit.dp
@Composable
fun ExampleSubcomposeLayout() {
SubcomposeLayout { constraints ->
// Step 1: 첫 번째 컴포저블을 측정
val headerPlaceable = subcompose("header") {
Box(
modifier = Modifier
.background(Color.Blue)
.height(50.dp)
)
}.first().measure(constraints)
// Step 2: 두 번째 컴포저블을 측정
val contentPlaceable = subcompose("content") {
Box(
modifier = Modifier
.background(Color.Red)
.height(100.dp)
)
}.first().measure(constraints)
// Step 3: 전체 레이아웃 크기 결정 및 자식 배치
layout(constraints.maxWidth, headerPlaceable.height + contentPlaceable.height) {
headerPlaceable.place(0, 0)
contentPlaceable.place(0, headerPlaceable.height)
}
}
}
코드 설명
- subcompose("header")
- "header"라는 키를 사용해 헤더 컴포저블을 정의.
- 이 키는 중복을 방지하고 특정 요소를 재구성할 때 활용.
- measure(constraints)
- 헤더와 콘텐츠를 부모의 제약 조건에 맞춰 측정.
- 크기를 결정하고 Placeable 객체로 반환.
- layout(width, height)
- 부모 레이아웃의 전체 크기를 결정.
- 각 자식 요소를 특정 위치에 배치.
실제 사용 예시
상황 1: 자식 크기에 따라 레이아웃 동기화
@Composable
fun SyncSizeExample() {
SubcomposeLayout { constraints ->
// Box2 측정
val box2Placeable = subcompose("Box2") {
Box(
modifier = Modifier
.background(Color.Green)
.height(60.dp)
)
}.first().measure(constraints)
// Box1 측정, 크기를 Box2에 맞춤
val box1Placeable = subcompose("Box1") {
Box(
modifier = Modifier
.background(Color.Yellow)
.height(box2Placeable.height.toDp()) // Box2의 높이에 맞춤
)
}.first().measure(constraints)
// 전체 레이아웃 크기 결정 및 배치
layout(constraints.maxWidth, box1Placeable.height + box2Placeable.height) {
box1Placeable.place(0, 0)
box2Placeable.place(0, box1Placeable.height)
}
}
}
장단점
장점
- 순차적인 측정 및 배치 가능.
- 요소 간의 의존 관계가 있는 복잡한 레이아웃에 유용.
- 특정 요소를 조건부로 렌더링해 성능 최적화 가능.
단점
- 코드가 복잡해질 수 있음.
- 간단한 레이아웃에서는 불필요한 오버헤드.
SubcomposeLayout vs 일반 레이아웃
특징 일반 레이아웃 SubcomposeLayout
측정 순서 | 모든 자식 동시에 측정 | 순차적으로 측정 가능 |
유연성 | 제한적 | 매우 유연 |
성능 | 간단한 레이아웃에서 더 빠름 | 복잡한 레이아웃에 최적화 |
코드 복잡도 | 간단 | 복잡해질 가능성 |
언제 사용해야 할까?
- UI 요소 간 크기 또는 위치 의존성이 있는 복잡한 레이아웃.
- 성능을 최적화하거나, 순차적인 측정/배치가 필수인 경우.
예:
- Box2의 크기에 따라 Box1을 동기화해야 하는 경우.
- 동적으로 크기가 변하는 UI 컴포넌트.
반응형