[Android] Jetpack Compose (3)

https://developer.android.com/codelabs/jetpack-compose-migration?hl=ko#0 

마지막으로 Compose를 활용해서 리스트 목록과 애니메이션을 추가하는 기능을 알아봤다.

Jetpack Compose에서는 리싸이클러뷰처럼 어댑터와 레이아웃을 작성할 필요가 없다.

LazyColumn, LazyRow, LazyVerticalGrid 처럼 Composable 함수를 사용해서 작성한다.

 

Compose 함수로 UI를 구성할 때, Ui 상태를 저장하기 위해서 메시지 확장을 추적해야 한다.

이 추적 기능을 구현하기 위해서 remember와 mutableStateOf 함수를 사용해야 한다.

 

Message Card 생성

리스트 뷰의 각 아이템에 애니메이션을 적용하고, 아이템 데이터를 그려줄 메시지 카드를 생성했다.

우선 가로 디자인 구조를 위해서 Row 스코를 추가한다.

 

    // 메시지 근처에 패딩 추가
    Row(modifier = Modifier.padding(all = 8.dp))

 

이 후에 Row의 첫 번째 값으로 이미지 뷰를 넣어준다. 

텍스트와의 공간을 두기 위해서 Spacer도 추가했다.

 

        // 이미지  추가
        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))

 

이제 메시지 확장 여부를 추적하기 위한 변수로 remember를 선언한다.

remember 변수는 ui 상태를 기억하는 기능을 한다.

 

        // 메시지 확장 여부를 추적하기 위한 변수 (remember로 ui 상태 기억)
        var isExpanded by remember { mutableStateOf(false) }
        // surfacecolor를 적용 : 다른 색상으로 점진적 변화
        // primary -> surface로 점진적 수정 배경 애니메이션 적용
        val surfaceColor by animateColorAsState(
            if (isExpanded) MaterialTheme.colors.primary
            else MaterialTheme.colors.surface
        )

 

isExpanded,surfaceColor 변수를 선언했다.

isExpanded는 메시지 확장 여부를 감지하고, surfaceColor는 애니메이션 색상을 변경한다.

메시지가 클릭으로 확장되었다면, 확장 여부를 통해서 배경 색을 변경하는 코드를 작성하기 위함이다.

 

이제 메시지 작성자와 메시지 내용을 수직 뷰로 구현한다.

 

// 수직 정렬
        //isExpanded가 클릭 상태인지 확인
        // 이 column을 클릭하면, isExpanded 변수를 토글(확장)함
        Column (modifier = Modifier.clickable { isExpanded=!isExpanded })

 

Colum 스코프를 활용해서, Colum으로 감싸진 메시지와 사용자 부분을 클릭하면 isExpanded가 활성화 된다.

사용자를 나타내는 msg.author로 Text를 추가했다.

그 이후에 작성자와 메시지 사이의 공간을 넣고 애니메이션을 통해서 클릭 시 색상을 변경한다.

            Text(
                text = msg.author,
                // 매핑 된 색상 변경  :Surface를 활용한 테마 변경
                color = MaterialTheme.colors.secondaryVariant,
                // 텍스트 스타일 지정
                style = MaterialTheme.typography.subtitle2
            )
            // 텍스트 사이에 패딩 추가
            Spacer(modifier = Modifier.height(4.dp))

            // 텍스트에 도형 추가 (텍스트를 감싸는 이미지
            Surface(
                shape = MaterialTheme.shapes.medium, elevation = 1.dp,
                color = surfaceColor, // 위에서 적용한 점진적 애니메이션 칼라 적용
                // 점차적인 표면 크기 변화 적용 (1dp)
                modifier = Modifier.animateContentSize().padding(1.dp)
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // 메세지가 확장 상태라면 모든 메시지를 보여주고
                    // 확장 상태가 아니라면 1줄만 보여주기
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.body2
                )
            }

 

LazyColumn 작성

 

이제 새로운 Composable 함수를 선언해서, 각 메시지 카드에 대한 리스트뷰를 구현한다.

텍스트 메시지는 위에서 아래로 확인하므로, Column 함수를 사용했다.

@Composable
fun Conversation(messages : List<Message>){
    LazyColumn{
        items(messages){message->
            MessageCard2(msg = message)
        }
    }
}

 

Sample Data 생성

 

각 메시지 샘플을 데이터로 불러왔다.

메시지 샘플을 적용하기 위한 데이터 클래스 모델도 생성했다.

 

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

 

샘플 데이터는 object 클래스로 제작되었으며, conversationSample 리스트를 통해서 데이터를 관리한다.

 

object SampleData {
    // Sample conversation data
    val conversationSample = listOf(
        Message(
            "Colleague",
            "Test...Test...Test..."
        ),
        Message(
            "Colleague",
            "List of Android versions:\n" +
                    "Android KitKat (API 19)\n" +
                    "Android Lollipop (API 21)\n" +
                    "Android Marshmallow (API 23)\n" +
                    "Android Nougat (API 24)\n" +
                    "Android Oreo (API 26)\n" +
                    "Android Pie (API 28)\n" +
                    "Android 10 (API 29)\n" +
                    "Android 11 (API 30)\n" +
                    "Android 12 (API 31)\n"
        ),
        Message(
            "Colleague",
            "I think Kotlin is my favorite programming language.\n" +
                    "It's so much fun!"
        ),
        Message(
            "Colleague",
            "Searching for alternatives to XML layouts..."
        ),
        Message(
            "Colleague",
            "Hey, take a look at Jetpack Compose, it's great!\n" +
                    "It's the Android's modern toolkit for building native UI." +
                    "It simplifies and accelerates UI development on Android." +
                    "Less code, powerful tools, and intuitive Kotlin APIs :)"
        ),
        Message(
            "Colleague",
            "It's available from API 21+ :)"
        ),
        Message(
            "Colleague",
            "Writing Kotlin for UI seems so natural, Compose where have you been all my life?"
        ),
        Message(
            "Colleague",
            "Android Studio next version's name is Arctic Fox"
        ),
        Message(
            "Colleague",
            "Android Studio Arctic Fox tooling for Compose is top notch ^_^"
        ),
        Message(
            "Colleague",
            "I didn't know you can now run the emulator directly from Android Studio"
        ),
        Message(
            "Colleague",
            "Compose Previews are great to check quickly how a composable layout looks like"
        ),
        Message(
            "Colleague",
            "Previews are also interactive after enabling the experimental setting"
        ),
        Message(
            "Colleague",
            "Have you tried writing build.gradle with KTS?"
        ),
    )
}

 

Preview를 통해서 작성한 코드를 살펴보면 아래와 같은 뷰를 얻을 수 있다.

 

@Preview
@Composable
fun PreviewConversation(){
    // 제작해둔 테마 사용
    MyApplicationTheme {
        Conversation(messages = SampleData.conversationSample)
    }
}

 

[preview로 확인한 UI]

 

 

message card를 클릭할 경우, 메시지 뷰가 확장 되면서 모든 텍스트 내용을 볼 수 있다.

이 때 animateColorAsState로 설정된 앱 테마 색상으로 변경된다.

 

 

모든 코드는 개발 문서의 Jetpack Compose 이전 전략을 참고했다.

https://developer.android.com/codelabs/jetpack-compose-migration?hl=ko#0 

 

Jetpack Compose로 이전  |  Android Developers

이 Codelab에서는 뷰 시스템의 화면 일부를 Jetpack Compose로 이전하는 방법을 알아봅니다.

developer.android.com