Box Layout이란?
Box Layout은 여러 위젯를 겹쳐서 놓을 수 있는 레이아웃이다. Box 내부의 Child Compose들은 Modifier.align에 자신의 위치를 지정함으로써 Box 내부의 어떤 공간에 보여질지를 결정할 수 있다. 두개의 위젯을 같은 위치로 설정하면 위젯 위에 다른 위젯 겹쳐 지는 것 또한 가능하다.
Box Layout은 기존 Frame Layout과 동작이 동일한데, 화면 오른쪽 아래 버튼을 만들거나 할 때 유용하다.
예를 들어 아래 코드와 같이 Box 내부에 다음과 같이 align이 없는 상태로 Text를 쓰게되면
@Preview(showBackground = true, widthDp = 120, heightDp = 200)
@Composable
fun KotlinWorldBox1() {
Box {
Text(text = "Kotlin")
Text(text = "World")
Text(text = "Blog")
}
}
아래 그림1과 같이 텍스트가 겹쳐서 나오게 된다.
이 텍스트를 순서대로 왼쪽 위, 중앙, 오른쪽 아래에 배치시키기 위해서는 다음과 같이 옵션을 주면 된다.
@Preview(showBackground = true, widthDp = 120, heightDp = 200)
@Composable
fun KotlinWorldBox() {
Box {
Text(modifier = Modifier.align(Alignment.TopStart), text = "Kotlin")
Text(modifier = Modifier.align(Alignment.Center), text = "World")
Text(modifier = Modifier.align(Alignment.BottomEnd), text = "Blog")
}
}
Box 내부 살펴보기
Box는 modifier, contentAlignment, propateMinConstraints, content 네가지 변수를 받는다.
@Composable
inline fun Box(
modifier: Modifier = Modifier,
contentAlignment: Alignment = Alignment.TopStart,
propagateMinConstraints: Boolean = false,
content: @Composable BoxScope.() -> Unit
)
- modifier(수정자) : 박스의 크기, 클릭 이벤트 등을 정의 가능
- contentAlignment : 자식의 기본 정렬 방식을 결정
- propagateMinConstraints : 최소 제약 조건을 전파시키는지 여부
- content : Box 레이아웃에 들어갈 레이아웃과 위젯이 람다식으로 들어가는 부분
modifier은 다른 레이아웃, 위젯들과 모두 공통으로 쓰이므로 이 글에서는 다루지 않는다. 나머지 또한 중요하지 않으므로, 그려지는 관점에서 중요한 contentAlignment와 contentAlignment만 보도록 하자.
ContentAlignment
contentAligment는 Box 내부의 자식 위젯들의 기본 위치를 지정하는 값이다. 이 값이 지정되면 BoxScope에 있는 자식들의 기본 align이 이 값으로 지정된다.
예를 들어 아래와 같이 ContentAlignment를 지정할 경우 BoxScope 내부의 세개의 Text는 align이 BottomEnd(오른쪽 아래)로 지정된다.
@Preview(showBackground = true, widthDp = 120, heightDp = 200)
@Composable
fun KotlinWorldBox1() {
Box(contentAlignment = Alignment.BottomEnd) {
Text(text = "Kotlin")
Text(text = "World")
Text(text = "Blog")
}
}
하지만, 이 값은 내부의 자식 위젯들의 Modifier에 align이 적용된 경우에는 동작하지 않는다. 예를 들어 아래와 같은 코드를 수행할 경우
자식들이 이미 자체 align을 가지고 있기 때문에 Box의 alignment가 전파되지 않는다.
@Preview(showBackground = true, widthDp = 120, heightDp = 200)
@Composable
fun KotlinWorldBox() {
Box(contentAlignment = Alignment.BottomEnd) {
Text(modifier = Modifier.align(Alignment.TopStart), text = "Kotlin")
Text(modifier = Modifier.align(Alignment.Center), text = "World")
Text(modifier = Modifier.align(Alignment.BottomEnd), text = "Blog")
}
}
propagateMinConstraints
Box에서 이 값은 지정하지 않을 경우 false로 되어 있다. 만약 이 값이 false로 되어 있으면 Box의 MinConstraint가 적용되지 않은 상태로 Child Widget들이 measure된다. 하지만 이 값이 true가 된다면 Box의 MinContraint가 적용된 상태로 Child들이 measure된다.
즉, 이 값이 true면 Box의 min size constraint 가 child에도 적용이 되게 된다.