이 포스트는 Android 공식 홈페이지의 Jetpack Compose 튜토리얼 을 기반으로 작성되었습니다.
이번 포스트에서는 Jetpack Compose를 공부한 기록을 남겨보기로 했다.
튜토리얼이 꽤 길고 그만큼 Compose에 대한 내용도 많기 때문에 시리즈로 포스트가 구성될 것 같다.
Jetpack Compose는 네이티브 Android UI를 빌드하기 위한 최신 도구 키트이다.
기존의 xml 기반 레이아웃 작성 방식과 다르게 Jetpack Compose를 사용하면 더 적은 코드, 강력한 도구, 직관적인 Kotlin API로 안드로이드에서 UI 개발을 간소화하고 가속화할 수 있습니다.
이번 포스트에서는 선언형 함수를 사용하여 간단한 UI 구성요소를 빌드해보도록 한다.
Jetpack Compose는 Composable 함수를 중심으로 빌드되어있다. Composable 함수를 사용하여 Programmatic 하게 앱의 UI를 정의할 수 있다.
Composable 함수를 만들기 위해서는 함수 이름에 @Composable
주석을 추가하기만 하면 된다.
Android 스튜디오 최신버전에서 새 프로젝트를 생성하면 아래처럼 처음 MainActivity 가 생성된다.
해당 프로젝트를 빌드 후 실행하면 빈 화면에 "Hello world!" 라는 텍스트가 표시된다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text("Hello world!")
}
}
}
setContent
블록은 Composable 함수가 호출되는 활동의 레이아웃을 정의한다.
이 때 Composable 함수는 다른 Composable 함수에서만 호출할 수 있다.
위 화면처럼 텍스트를 표시하려면 Composable 함수인 Text
함수를 호출하면 된다.
Text
함수처럼 기존에 구성되어 있는 Composable 함수가 아닌 새로 구현한 함수를 Composable로 정의하려면 @Composable
주석을 추가하면 된다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MessageCard("Android")
}
}
}
@Composable
fun MessageCard(name: String) {
Text(text = "Hello $name!")
}
MessageCard
함수를 정의하고 @Composable
주석을 추가한다. 이러면 MessageCard
함수가 Composable 함수가 된다.
추가로 @Preview
주석을 사용하면 앱을 빌드해서 실행해보지 않아도 안드로이드 스튜디오 내에서 미리볼 수 있다. 단, @Preview
주석은 매개변수를 사용하지 않는 함수에 사용해야한다.
@Composable
fun MessageCard(name: String) {
Text(text = "Hello $name!")
}
@Preview
@Composable
fun PreviewMessageCard() {
MessageCard("Android")
}
Message
객체에 작성자 이름, 메시지 내용을 표시하여 일반 String 보다 더욱 복잡하게 만든다.
MessageCard
함수에 매개변수로 Message
객체를 허용하도록 하고 MessageCard
Composable 함수 내에 Text
함수들을 추가한다.
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MessageCard(Message("Android", "Jetpack Compose"))
}
}
}
data class Message(val author: String, val body: String)
@Composable
fun MessageCard(msg: Message) {
Text(text = msg.author)
Text(text = msg.body)
}
@Preview
@Composable
fun PreviewMessageCard() {
MessageCard(
msg = Message("Colleague", "Hey, take a look at Jetpack Compose, it's great!")
)
}
그러나 위치 정렬 방식에 대한 지정을 해주지 않았기 때문에 동일한 위치에 2개의 텍스트가 표시된다.
Column
함수를 사용하면 요소를 수직으로 정렬할 수 있다.
@Composable
fun MessageCard(msg: Message) {
Column {
Text(text = msg.author)
Text(text = msg.body)
}
}
반대로 Row
함수를 사용하면 요소들을 수평으로 정렬할 수 있고 Box
를 사용하면 요소를 쌓을 수 있다.
발신자의 프로필 사진을 추가하여 MessageCard
를 보한다.
이미지를 추가할때는 Image
함수를 추가하면 된다.
@Composable
fun MessageCard(msg: Message) {
Row {
Image(
painter = painterResource(R.drawable.profile_picture),
contentDescription = "Contact profile picture",
)
Column {
Text(text = msg.author)
Text(text = msg.body)
}
}
}
모든 구성 요소가 레이아웃에 배치되었지만 각 요소별 크기가 적절하지 않고 간격이 균등하지 않은 등 문제가 많다.
이런 부분을 해결하기 위해 Compose는 modifier
를 사용한다.
modifier
를 이용해 컴포저블 요소의 크기, 레이아웃, 모양 등을 변경하거나 클릭 가능하게 만드는 등 상호작용을 추가할 수 있다.
@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)
}
}
}