[Android] Jetpack Compose (2)

 

UI 디자인하기

이전 포스팅에서 text뷰와 textField를 jetpack Compose 방식으로 적용하는 방법을 배웠다.

이제 화면을 담당하는 레이아웃과 그 내부의 코드를 작성하는 방법을 공부해야 한다.

이 방식을 익혀서 Activity에서 xml을 통해 작성한 레이아웃을 Jetpack Compose로 구현하는 연습을 한다.

 

 

연속 텍스트와 이미지 적용하기

구성 함수를 통해서 UI 계층 구조를 빌드하는 과정으로 연속 텍스트와 이미지를 적용한다.

간단한 메시지 함수를 빌드하고, 메시지를 표현하는 코드를 작성했다.

우선 메시지 데이터를 나타낼 data class를 선언했다.

// 여러 텍스트 추가
data class Message(
    val author : String, val body : String,
)

해당 클래스는 작성자와 메모 정보를 가지고있으며, 메시지 객체를 나타낼 정보를 포함하고 있다.

MessageCard Composable 함수와 PreviewMessageCard Preview Composable 함수를 선언했다.

MessageCard는 수직 정렬을 통해서 메시지 리스트를 그려주기 위한 함수이고,

PreviewMessageCard2는 작성 코드를 미리보기하기 위한 함수이다.

PreviewMessageCard를 저번 프로젝트에서 선언했으므로, PreviewMessageCard2로 재선언했다.
Column을 통해서 수직 정렬 된 텍스트(작성자 - 내용)이 화면에 연속으로 그려지게 된다.

 

@Composable
fun MessageCard(msg:Message) {
    // 디자인 구조를 위한 Row 스코프 추가

        // 수직 정렬
        Column {
            Text(text = msg.author)
            Text(text = msg.body)
        }
}

@Preview
@Composable
fun PreviewMessageCard2() {
    MessageCard(
        msg = Message(
            "Colleague",
            "Hey, take a look at Jetpack Compose, it's great!"
        )
    )
}

다음으로 메시지 카드에 이미지를 추가하기 위해서 Image 함수를 사용했다.

Image 함수를 통해서 그려줄 이미지와 사진 설명을 부여했다.

이 후에 Row scope를 통해서 이미지와 다중 텍스트를 수평 정렬했다.

@Composable
fun MessageCard(msg:Message) {
    // 디자인 구조를 위한 Row 스코프 추가
    Row{
        // 이미지  추가
        Image(
            painter = painterResource(id = R.drawable.ic_garbage),
            contentDescription ="Contack profile picture"
        )

        // 수직 정렬
        Column {
            Text(text = msg.author)
            Text(text = msg.body)
        }
    }
}

아래와 같이 다중 텍스트와 이미지 뷰가 그려진 레이아웃을 얻을 수 있으며, Preview를 통해서 미리보기 기능도 지원했다.

layout 적용 이미지

 

디자인 사이에 패딩(space) 추가 

메시지와 이미지 레이아웃을 구조에 맞도록 구성하였으나,요소의 간격이 균등하지 않거나 이미지가 너무 큰 등의 문제가 발생했다.

이를 해결하기 위해서 Compose Modifier(수정자)를 사용해야 한다.

Composable 크기, 레이아웃, 모양을 변경하거나 요소를 클릭 가능하게 만드는 등의 상위 수준 상호작용을 추가할 있다.

MessageCard Composable을 아래와 같이 수정했다.

@Composable
fun MessageCard(msg:Message) {
    // 디자인 구조를 위한 Row 스코프 추가

    // 메시지 근처에 패딩 추가
    Row(modifier = Modifier.padding(all = 8.dp)){
        // 이미지  추가
        Image(
            painter = painterResource(id = R.drawable.ic_garbage),
            contentDescription ="Contack profile picture",
            // 이미지에 페딩 추가
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
        )
        // horizontal 공간 추가 (이미지와 콜럼 사이)
        Spacer(modifier = Modifier.width(8.dp))

        // 수직 정렬
        Column {
            Text(text = msg.author)
            // 텍스트 사이에 패딩 추가
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}

Row에 패딩을 추가하여 전체 뷰의 외부 간격을 추가했으며,

Image에 사이즈와 모양을 지정하고 이미지와 텍스트 사이에 Spacer를 통해서 너비 공간을 두었다.

마지막으로 텍스트 사이에 Spacer를 두어 텍스트 사이에 높이 간격을 설정했다.

왼쪽이 수정한 뷰이고, 오른쪽이 이전에 작성한 뷰이다.

간격과 이미지 크기가 변경되었으며, 이 과정을 통해서 원하는 뷰를 얻을 수 있었다.

 

 

Material Design 사용하기

Compose Material Design 원칙을 사용해서 UI 요소를 빌드한다.

Compose의 많은 UI 요소가 Meterial Design을 간편하게 사용할 수 있도록 지원한다.

위에서 작성한 메시지 디자인에 레이아웃이 생겼지만, 좋은 디자인이라고 할 수 없다.

Jetpack Compose는 Material Design 및 UI 요소를 즉시 사용 가능하도록 구현한다.

Meterial Design 스타일 지정을 사용해서 MessageCard를 재구성한다.

 

우선 ComposeTutorialTheme와 Surface로 MessageCard 함수를 래핑한다.

@Preview 함수와 setContent 함수에서도 이 작업을 실행하여, 앱 테마에 정의된 스타일을 상속하여 앱 전체에 일관성을 보장한다.

Material Design은 Color, Typography, Shape 세 가지 핵심 요소를 중심으로 이루어진다.

 

먼저 Color 디자인을 적용해서 이미지의 테두리 색상과, 메시지 작성자의 텍스트 색상을 변경하였다.

        // 이미지  추가
        Image(
            painter = painterResource(id = R.drawable.ic_garbage),
            contentDescription ="Contack profile picture",
            // 이미지에 페딩 추가
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                    //이미지에 테두리 추가
                .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape)
        )
        // horizontal 공간 추가 (이미지와 콜럼 사이)
        Spacer(modifier = Modifier.width(8.dp))

        // 수직 정렬
        Column {
            Text(
                text = msg.author,
                // 매핑 된 색상 변경  :Surface를 활용한 테마 변경
                color = MaterialTheme.colors.secondaryVariant
            )
            // 텍스트 사이에 패딩 추가
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }

border를 통해서 이미지 테두리를 설정할 때 Theme에 있는 secondary color 속성으로 테두리 색을 변경하였으며,

텍스트 작성자 TextView에 Theme의 secondaryVariant color 속성으로 글자 색을 변경했다.

결과로 아래의 레이아웃을 얻을 수 있었다.

 

Jetpack을 활용해서 kotlin 코드로 디자인을 변경하는 방법을 알아봤다.

다음 포스팅에서 더 다양한 디자인 변경 방법과 리스트를 표현하는 방법을 공부해야 겠다.