읽기 전

  • 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
  • 개인적으로 사용해보면서 배운 점을 정리한 글입니다.

Jetpack Compose의 레이아웃 코드랩에서 실습한 내용들을 정리합니다. 앱의 디자인을 위해 Material Design Component 도입을 위한 Scaffold 레이아웃과 기본적인 사용법에 대해 다룹니다. 코드랩 실습에 요구되는 시간은 대략 1시간 정도로 학습 목적을 고려하면 대략 2 - 3시간 정도를 투자해야 합니다. 분량이 너무 많아 챕터 별로 분할하여 업로드합니다.

Material Component(머티리얼 구성요소)

앱을 구현하면서 디자인 측면을 넘어서 UI 컴포넌트까지 Material 라이브러리는 광범위하게 영향을 끼친다. 컴포즈에서는 특히 더욱 그러한데 그 중에서도 Scaffold는 가장 높은 수준의 컴포저블이다.

Scaffold

Scaffold를 사용하면 기본 머티리얼 디자인 레이아웃 구조로 UI를 구현할 수 있으며 페이지 구성 시 자주 쓰이는 TopAppBar, BottomAppBar, FloatingActionButton 등 최상위 머티리얼 컴포넌트를 위한 슬롯(공간)을 제공한다.

Scaffold 본문에 Text 컴포저블을 배치해보자.

@Composable
fun LayoutsCodelab() {
    Scaffold { innerPadding ->
        Text(text = "Hi there!", modifier = Modifier.padding(innerPadding))
    }
}

Scaffold 컴포저블의 파라미터는 @Composable (InnerPadding) -> Unit의 본문 content를 제외하고 선택적으로 부여할 수 있다. 하위 람다 함수를 사용하여 본문 컴포저블을 정의할 수 있으며 매개변수로 패딩을 받는다. 해당 패딩은 화면의 항목을 적절히 제한하도록 컨텐츠 루트 컴포저블에 적용한다고 한다.

화면의 기본 컨텐츠를 Vertical하게 배치한다고 가정하고 Column 컴포저블 내부에 쌓아보자.

@Composable
fun LayoutsCodelab() {
    Scaffold { innerPadding ->
        Column(modifier = Modifier.padding(innerPadding)) {
            Text(text = "Hi there!")
            Text(text = "Thanks for going through the Layouts codelab")
        }
    }
}

가급적이면 코드 재사용과 테스팅 편의를 위해 작은 단위로 코드를 구조화하면 좋다. 본문에 들어갈 컴포저블을 따로 컴포저블 함수로 구성하자.

@Composable
fun LayoutsCodelab() {
    Scaffold { innerPadding ->
        BodyContent(Modifier.padding(innerPadding))
    }
}

@Composable
fun BodyContent(modifier: Modifier = Modifier) {
    Column(modifier = modifier) {
        Text(text = "Hi there!")
        Text(text = "Thanks for going through the Layouts codelab")
    }
}

TopAppBar

많은 앱은 상단 AppBar를 갖는다. Scaffold도 이를 위해 @Composable () -> Unit 유형의 topBar라는 파라미터를 사용하여 상단 AppBar 슬롯에 컴포저블을 배치할 수 있다. h3 스타일의 텍스트를 상단 앱바로 사용하려면 다음과 같이 작성하면 된다.

@Composable
fun LayoutsCodelab() {
    Scaffold(
        topBar = {
            Text(
                text = "LayoutsCodelab",
                style = MaterialTheme.typography.h3
            )
        }
    ) { innerPadding ->
        BodyContent(Modifier.padding(innerPadding))
    }
}

Codelab_Jetpack_Compose_layout_016

컴포저블 함수 작성 결과는 위 그림과 같다.

단순 텍스트로 상단 앱 바를 구성하기보다 title, 탐색 아이콘, 작업용 슬롯, navigation icon이 있는 TopAppBar 컴포저블을 사용할 수 있다. 기존 텍스트로만 구성한 상단 앱 바를 TopAppBar로 교체하고 title 슬롯에 Text 컴포저블을 정의해보자.

@Composable
fun LayoutsCodelab() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(text = "LayoutsCodelab")
                }
            )
        }
    ) { innerPadding ->
        BodyContent(Modifier.padding(innerPadding))
    }
}

Codelab_Jetpack_Compose_layout_017

프로젝트에 적용된 테마에 맞춰서 상단 앱 바가 구성되었음을 확인할 수 있다. TopAppBar를 사용했으니 타이틀 말고도 다른 파라미터를 사용할 수 있다. 상단 앱 바에서 자주 보던 좌측 navigationIcon이나 우측 작업 버튼 등을 정의할 수 있다. 우측 작업 버튼을 배치해보자.

@Composable
fun LayoutsCodelab() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(text = "LayoutsCodelab")
                },
                actions = {
                    IconButton(onClick = { /* doSomething() */ }) {
                        Icon(Icons.Filled.Favorite, contentDescription = null)
                    }
                }
            )
        }
    ) { innerPadding ->
        BodyContent(Modifier.padding(innerPadding))
    }
}

Codelab_Jetpack_Compose_layout_018

Preview로 컴포저블 함수를 출력한 결과 작업버튼이 잘 배치되었음을 확인할 수 있다.

추가 Modifier 배치

Modifier는 컴포저블의 padding, background 등 기본적인 모양새를 결정한다. 따라서, 새로운 컴포저블 생성 시 기본값이 Modifier로 지정된 modifier 매개변수를 정의해두면 컴포저블 함수의 재사용성이 좋아진다. 앞서 작성했던 BodyContent 컴포저블 함수에 파라미터로 Modifier를 정의하여 하위 요소들을 감싸는 Column 컴포저블의 modifier 파라미터로 입력했었다. 패딩을 Column 컴포저블에 더 추가하고 싶다면 두 가지로 정리할 수 있다.

  1. BodyContent 컴포저블 함수가 호출될 때마다 추가 패딩이 적용되도록 modifier padding을 하위 요소에 적용한다.
@Composable
fun BodyContent(modifier: Modifier = Modifier) {
    Column(modifier = modifier.padding(8.dp)) {
        Text(text = "Hi there!")
        Text(text = "Thanks for going through the Layouts codelab")
    }
}

Modifier가 컴포저블의 고유한 속성이라면 1번 방법처럼 함수 내부에 선언한다.

  1. 추가 padding이 필요할 때만 컴포저블 함수 선언 시 Modifier 적용
@Composable
fun LayoutsCodelab() {
    Scaffold(...) { innerPadding ->
        BodyContent(Modifier.padding(innerPadding).padding(8.dp))
    }
}

Modifier가 컴포저블의 고유한 속성이 아니라 주입해야 한다면 외부로부터 입력받도록 작성한다.

참고자료

  1. Google Codelab - Jetpack Compose Layout #5 머티리얼 구성요소

+ Recent posts