Jetpack Compose 레이아웃 시작하기
Jetpack Compose는 UI를 위한 라이브러리이므로, UI컴포넌트를 화면상에 배치하기 위한 Layout이 존재한다. 만약 Layout을 지정하지 않고 이모지와 텍스트를 써보면 다음과 같이 나타난다.
@Preview
@Composable
fun TestView(){
EmojiView()
TitleView()
}
우리는 여기에 Column 레이아웃을 추가하여 다음과 같이 바꿀 수 있다.
@Preview
@Composable
fun TestView(){
Column() {
EmojiView()
TitleView()
}
}
레이아웃은 위젯을 원하는 위치에 배치시켜 자신이 원하는 뷰를 만들기 위한 필수 사항이다. 자 이제 Compose에는 어떤 레이아웃이 지원되는지 알아보자.
Layout의 종류 : Column, Row, Box, BoxWithConstraints, ConstraintLayout
JetpackCompose는 Column, Row, Box, BoxWithConstraints, ConstraintLayout 4가지 레이아웃을 지원한다.
보통 문서에는 BoxWithConstraints, ConstraintLayout을 제외한 Column, Row, Box만을 소개하고 있는데 이 글에서는 5가지를 모두 설명하고자 한다. 아래 그림3은 Android Developers 사이트에서 가져온 이미지인데, 여기에는 BoxWithConstraints, Constraint Layout이 존재하지 않는다.
각 Layout에 대한 요약은 다음과 같다.
- Column: 위젯을 화면에 수직(vertical) 순서로 배치. LinearLayout(orientation=vertical)과 동일
- Row: 위젯을 화면에 수평(horizontal) 순서로 배치. LinearLayout(orientation=horizontal)과 동일
- Box: 위젯을 다른 항목의 위에 배치. FrameLayout과 동일
- BoxWithConstraints : Box의 기능을 확장하여 레이아웃 Constraint(최대 크기, 최소 크기)에 접근할 수 있도록 만든 레이아웃
- ConstraintLayout: 위젯을 다른 위젯의 위치에 상대적으로 배치. 기존 ConstraintLayout과 동일
Column
Column 레이아웃은 항목을 화면에 수직(vertical) 순서로 배치하는 레이아웃이다.
예를 들어 "Kotlin World", "Blog" 라는 두개의 텍스트를 Column을 이용해 배치 시키는 코드는 다음과 같다.
@Preview(showBackground = true)
@Composable
fun KotlinWorldBlog(){
Column() {
Text(text = "Kotlin World")
Text(text = "Blog")
}
}
Row
Row 레이아웃은 화면에 수평(horizontal) 순서로 배치하는 레이아웃이다.
"Kotlin World", "Blog" 라는 두개의 텍스트를 수평으로 배치시켜서 "Kotlin World Blog"로 만들어 보자.
Row을 이용해 배치 시키는 코드는 다음과 같다.
@Preview(showBackground = true)
@Composable
fun KotlinWorldBlogRow(){
Row() {
Text(text = "Kotlin World ")
Text(text = "Blog")
}
}
Box
Box 레이아웃은 위젯을 다른 화면의 위에 배치시키는 레이아웃이다.
예를들어 "Kotlin World"를 왼쪽 위에 "Blog"를 오른쪽 아래에 배치 시키는 코드는 다음과 같다. Box 내부의 contentAlignment 프로퍼티를 이용해 배치시킬 위치를 적용이 가능하다. modifier에 관한 것은 다음 글부터 심화시켜서 다룰 예정이라, 지금은 간단히만 설명하면 Modifier 객체를 이용해 뷰의 크기를 조정하거나 padding(내부 여유 공간), margin(외부 여유 공간) 등을 주는 것이 가능하다는 것만 알아주도록 하자.
@Preview(showBackground = true)
@Composable
fun KotlinWorldBlogRow() {
Box(modifier = Modifier
.fillMaxWidth() // 너비(width) 꽉 채우기
.height(100.dp)) // 높이(height) 100dp 로 설정
{
Text(contentAlignment = Alignment.TopStart, text = "Kotlin World ")
Text(contentAlignment = Alignment.TopStart, text = "Blog")
}
}
BoxWithConstraints
BoxWithConstraints Layout은 Box와 똑같이 동작한다.
다른 점은 레이아웃의 Constraints(크기 최소, 최대 값)에 접근할 수 있도록 하여 크기마다 다른 레이아웃을 그려줘야 할 때 유용하다.
Constraint Layout
Constraint Layout은 위젯을 다른 위젯의 위치에 대해 상대적으로 배치시키는 레이아웃이다. 기존 xml에서 많이 활용되던 레이아웃인데 기존 xml에서는 성능상의 이점이 많았지만, Compose에서는 성능상의 이점은 없다. 따라서 Android 공식 사이트에서는 뷰가 복잡하거나 가독성이 떨어질 때만 ConstraintLayout을 이용하는 것을 권장하고 있다.
예를들어 "Kotlin World"와 "Blog"를 만든 후 ConstraintLayout 내부에 배치시키고 Kotlin World는 parent(Constraint Layout)에 대해 4dp의 top margin을 가지며, Blog는 textKotlinworld 밑에 배치시키고 16dp의 마진을 가지도록 만든다고 해보자. 코드는 다음과 같이 구성이 가능하다.
@Preview(showBackground = true)
@Composable
fun ConstraintLayoutKotlinWorld() {
ConstraintLayout(modifier = Modifier.fillMaxWidth().height(100.dp)) {
val (textKotlinWorld, textBlog) = createRefs()
Text(
text = "Kotlin World",
modifier = Modifier.constrainAs(textKotlinWorld) {
top.linkTo(parent.top, margin = 4.dp) // parent(ConstraintLayout)에 대한 Top 마진을 16dp로 만든다.
}
)
Text("Blog", Modifier.constrainAs(textBlog) {
top.linkTo(textKotlinWorld.bottom, margin = 16.dp) // textKolinWorld에 대한 마진을 16dp로 만든다.
})
}
}