본문 바로가기

프로그래밍/Android

Jetpack Compose 정리1.

기본 구성

Compose는 선언형 UI로, 기존의 xml을 사용하던 방식과는 다르다.
Activity에 @Composable 어노테이션을 붙여 사용하고, 여러 Compose의 코드들로 UI를 구성할 수 있다.

Compose를 사용했을 때의 장점은
코드 감소, 직관적, 빠른 개발 속도, 강력한 성능이라 할 수 있는데, 왜 이런 장점을 가지는지 공부하며 알아보자!

 

 

 

@Composable
fun MessageCard(msg: Message) {
    // Add padding around our message
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = "Contact profile picture",
            modifier = Modifier
                // Set image size to 40 dp
                .size(40.dp)
                // Clip image to be shaped as a circle
                .clip(CircleShape)
        )

        // Add a horizontal space between the image and the column
        Spacer(modifier = Modifier.width(8.dp))

        Column {
            Text(text = msg.author)
            // Add a vertical space between the author and message texts
            Spacer(modifier = Modifier.height(4.dp))
            Text(text = msg.body)
        }
    }
}

(https://developer.android.com/jetpack/compose/tutorial)

 

위와 같이 Column, Row를 이용해 Text의 배열을 정의할 수 있다.
modifier를 통해 xml의 속성을 정의하듯, text나 image의 size, color 등등을 모두 정의할 수 있다.

 

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


@Composable
fun MessageCard(msg: Message) {
    Row(modifier = Modifier.padding(all = 8.dp)) {
        Image(
            painter = painterResource(R.drawable.profile_picture),
            contentDescription = null,
            modifier = Modifier
                .size(40.dp)
                .clip(CircleShape)
                .border(1.5.dp, MaterialTheme.colors.secondaryVariant, CircleShape)
        )
        Spacer(modifier = Modifier.width(8.dp))

        // We keep track if the message is expanded or not in this
        // variable
        var isExpanded by remember { mutableStateOf(false) }
        // surfaceColor will be updated gradually from one color to the other
        val surfaceColor: Color by animateColorAsState(
            if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface,
        )

        // We toggle the isExpanded variable when we click on this Column
        Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
            Text(
                text = msg.author,
                color = MaterialTheme.colors.secondaryVariant,
                style = MaterialTheme.typography.subtitle2
            )

            Spacer(modifier = Modifier.height(4.dp))

            Surface(
                shape = MaterialTheme.shapes.medium,
                elevation = 1.dp,
                // surfaceColor color will be changing gradually from primary to surface
                color = surfaceColor,
                // animateContentSize will change the Surface size gradually
                modifier = Modifier.animateContentSize().padding(1.dp)
            ) {
                Text(
                    text = msg.body,
                    modifier = Modifier.padding(all = 4.dp),
                    // If the message is expanded, we display all its content
                    // otherwise we only display the first line
                    maxLines = if (isExpanded) Int.MAX_VALUE else 1,
                    style = MaterialTheme.typography.body2
                )
            }
        }
    }
}

Image의 경우painter를 이용해 drawable을 가져올 수 있고, Spacer를 이용해 margin과 같은 효과를 낼 수 있다.
Material Theme을 그대로 가져와 사용할 수 있고

val surfaceColor: Color by animateColorAsState(
            if (isExpanded) MaterialTheme.colors.primary else MaterialTheme.colors.surface,
        )

이렇게 animateColorAsState를 대리자로 설정하여, surfaceColor라는 변수의 값을 설정할 수 있다.
여기서 remember에 대해 이해하기 위해 Compose의 State에 대해 추가로 공부하여 포스팅해보자!

 

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

또 LazyColumn의 items를 이용하면, RecyclerView를 손쉽게 구현할 수 있다. 기존 RecyclerView는 구현하기 까다로운 부분이 많았는데 (Adater 등등), 이렇게 간단히 설정할 수 있다.

 

Column, Row, Box, LazyColumn 등의 요소와 modifier를 어떻게 사용하는지 Compose를 기초 구성하는 방법을 기록하기 위해 적어두었다.