1. 시작하기 전에
처음부터 Jetpack Compose는 뷰 상호 운용성으로 설계되었습니다. 즉, Compose와 뷰 시스템이 리소스를 공유하고 함께 작동하여 UI를 표시할 수 있습니다. 이 기능을 사용하면 Compose를 기존 뷰 기반 앱에 추가할 수 있습니다. 즉, Compose와 뷰가 전체 앱이 Compose에 완전히 포함될 때까지 코드베이스에 공존할 수 있습니다.
이 Codelab에서는 Juice Tracker 앱의 뷰 기반 목록 항목을 Compose로 변경합니다. 원하는 경우 Juice Tracker 뷰의 나머지 부분을 직접 변환할 수 있습니다.
뷰 기반의 UI를 사용하는 앱의 경우 전체 UI를 한 번에 재작성하지 않는 것이 좋습니다. 이 Codelab을 통해 뷰 기반 UI의 단일 뷰를 Compose 요소로 변환할 수 있습니다.
기본 요건
- 뷰 기반 UI에 관한 지식
- 뷰 기반 UI를 사용하여 앱을 빌드하는 방법에 관한 지식
- 람다를 비롯한 Kotlin 문법 사용 경험
- Jetpack Compose에서 앱을 빌드하는 방법에 관한 지식
학습할 내용
- Android 뷰로 빌드된 기존 화면에 Compose를 추가하는 방법
- 뷰 기반 앱에 추가된 컴포저블 함수를 미리 보는 방법
빌드할 항목
- Juice Tracker 앱에서 뷰 기반 목록 항목을 Compose로 변환합니다.
2. 시작 앱 개요
이 Codelab에서는 뷰를 사용하여 Android 앱 빌드의 Juice Tracker 앱 솔루션 코드를 시작 코드로 사용합니다. 시작 앱은 이미 Room 지속성 라이브러리를 사용하여 데이터를 저장합니다. 사용자는 주스 이름, 설명, 색상, 평점과 같은 주스 정보를 앱 데이터베이스에 추가할 수 있습니다.
이 Codelab에서는 뷰 기반 목록 항목을 Compose로 변환합니다.
이 Codelab의 시작 코드를 다운로드합니다.
시작하려면 시작 코드를 다운로드하세요.
GitHub 저장소를 클론하여 코드를 가져와도 됩니다.
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-juice-tracker.git $ cd basic-android-kotlin-compose-training-juice-tracker $ git checkout views
JuiceTracker
GitHub 저장소에서 코드를 둘러볼 수 있습니다.
3. Jetpack Compose 라이브러리 추가
Compose와 뷰는 주어진 화면에 공존할 수 있습니다. Compose에 일부 UI 요소를, 뷰 시스템에 다른 요소를 포함할 수 있습니다. 예를 들어 Compose에는 목록만 있고 나머지 화면은 뷰 시스템에 있을 수 있습니다.
다음 단계를 완료하여 Compose 라이브러리를 Juice Tracker 앱에 추가하세요.
- Android 스튜디오에서 Juice Tracker를 엽니다.
- 앱 수준
build.gradle.kts
를 엽니다. buildFeatures
블록에compose = true
플래그를 추가합니다.
buildFeatures {
//...
// Enable Jetpack Compose for this module
compose = true
}
이 플래그를 사용하면 Android 스튜디오에서 Compose를 사용할 수 있습니다. 이전 Codelab에서는 이 단계를 완료하지 않았습니다. 새 Android 스튜디오 Compose 템플릿 프로젝트를 만들 때 Android 스튜디오에서 이 코드가 자동으로 생성되기 때문입니다.
buildFeatures
아래에composeOptions
블록을 추가합니다.- 블록 내에서
kotlinCompilerExtensionVersion
을"1.5.1"
로 설정하여 Kotlin 컴파일러 버전을 설정합니다.
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
dependencies
섹션에서 Compose 종속 항목을 추가합니다. 뷰 기반 앱에 Compose를 추가하려면 다음 종속 항목이 필요합니다. 이러한 종속 항목은 Compose를 Activity와 통합하고, Compose 디자인 구성요소 라이브러리를 추가하고, Compose Jetpack 테마 설정을 지원하고, 더 나은 IDE 지원을 위한 도구를 제공하는 데 도움이 됩니다.
dependencies {
implementation(platform("androidx.compose:compose-bom:2023.06.01"))
// other dependencies
// Compose
implementation("androidx.activity:activity-compose:1.7.2")
implementation("androidx.compose.material3:material3")
implementation("com.google.accompanist:accompanist-themeadapter-material3:0.28.0")
debugImplementation("androidx.compose.ui:ui-tooling")
}
ComposeView 추가
ComposeView
는 Jetpack Compose UI 콘텐츠를 호스팅할 수 있는 Android 뷰입니다. setContent
를 사용하여 뷰의 구성 가능한 콘텐츠 함수를 제공합니다.
layout/list_item.xml
을 열고 Split 탭에서 미리보기를 확인합니다.
이 Codelab을 마치면 이 뷰가 컴포저블 함수로 대체됩니다.
JuiceListAdapter.kt
의 모든 위치에서ListItemBinding
을 삭제합니다.JuiceListViewHolder
클래스에서binding.root
를composeView
로 바꿉니다.
import androidx.compose.ui.platform.ComposeView
class JuiceListViewHolder(
private val onEdit: (Juice) -> Unit,
private val onDelete: (Juice) -> Unit
): RecyclerView.ViewHolder(composeView)
onCreateViewHolder()
폴더에서 다음 코드와 일치하도록return()
함수를 업데이트합니다.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): JuiceListViewHolder {
return JuiceListViewHolder(
ComposeView(parent.context),
onEdit,
onDelete
)
}
JuiceListViewHolder
클래스에서private
변수를 모두 삭제하고bind()
함수의 코드를 모두 삭제합니다. 이제JuiceListViewHolder
클래스가 다음 코드와 같이 표시됩니다.
class JuiceListViewHolder(
private val onEdit: (Juice) -> Unit,
private val onDelete: (Juice) -> Unit
) : RecyclerView.ViewHolder(composeView) {
fun bind(juice: Juice) {
}
}
- 이제
com.example.juicetracker.databinding.ListItemBinding
및android.view.LayoutInflater
가져오기를 삭제할 수 있습니다.
// Delete
import com.example.juicetracker.databinding.ListItemBinding
import android.view.LayoutInflater
layout/list_item.xml
파일을 삭제합니다.- Delete 대화상자에서 OK를 선택합니다.
4. 구성 가능한 함수 추가
이제 목록 항목을 내보내는 컴포저블 함수를 만듭니다. 컴포저블 함수는 Juice
및 두 가지 콜백 함수를 사용하여 목록 항목을 수정하고 삭제합니다.
JuiceListAdapter.kt
에서JuiceListAdapter
클래스 정의 뒤에ListItem()
이라는 구성 가능한 함수를 만듭니다.ListItem()
함수가Juice
객체 및 삭제를 위한 람다 콜백을 허용하도록 합니다.
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
@Composable
fun ListItem(
input: Juice,
onDelete: (Juice) -> Unit,
modifier: Modifier = Modifier
) {
}
만들려는 목록 항목의 미리보기를 확인합니다. 주스 아이콘과 주스 세부정보, 삭제 버튼 아이콘이 있습니다. 이러한 구성요소는 곧 구현할 예정입니다.
주스 아이콘 컴포저블 함수 만들기
JuiceListAdapter.kt
에서ListItem()
컴포저블 함수 뒤에color
및Modifier
를 사용하는 또 다른 컴포저블 함수JuiceIcon()
을 만듭니다.
@Composable
fun JuiceIcon(color: String, modifier: Modifier = Modifier) {
}
JuiceIcon()
함수 내에서 다음 코드와 같이color
를 위한 변수와 콘텐츠 설명을 추가합니다.
@Composable
fun JuiceIcon(color: String, modifier: Modifier = Modifier) {
val colorLabelMap = JuiceColor.values().associateBy { stringResource(it.label) }
val selectedColor = colorLabelMap[color]?.let { Color(it.color) }
val juiceIconContentDescription = stringResource(R.string.juice_color, color)
}
colorLabelMap
및 selectedColor
변수를 사용하여 사용자 선택과 관련된 색상 리소스를 가져옵니다.
Box
레이아웃을 추가하여 두 개의 아이콘ic_juice_color
와ic_juice_clear
를 층층이 표시합니다.ic_juice_color
아이콘에는 색조가 있으며 가운데 정렬됩니다.
import androidx.compose.foundation.layout.Box
Box(
modifier.semantics {
contentDescription = juiceIconContentDescription
}
) {
Icon(
painter = painterResource(R.drawable.ic_juice_color),
contentDescription = null,
tint = selectedColor ?: Color.Red,
modifier = Modifier.align(Alignment.Center)
)
Icon(painter = painterResource(R.drawable.ic_juice_clear), contentDescription = null)
}
구성 가능한 함수 구현에 관해 잘 알고 있으므로 구현 방법에 관한 세부정보는 제공하지 않습니다.
JuiceIcon()
을 미리 보는 함수를 추가합니다. 색상은Yellow
로 전달합니다.
import androidx.compose.ui.tooling.preview.Preview
@Preview
@Composable
fun PreviewJuiceIcon() {
JuiceIcon("Yellow")
}
주스 세부정보 컴포저블 함수 만들기
JuiceListAdapter.kt
에서 주스 세부정보를 표시할 또 다른 구성 가능한 함수를 추가해야 합니다. 이름과 설명에 관한 구성 가능한 함수 Text
두 개와 평점 표시기를 표시하는 열 레이아웃도 필요합니다. 그러려면 다음 단계를 완료하세요.
- 다음 코드와 같이
Juice
객체와Modifier
를 사용하는JuiceDetails()
라는 구성 가능한 함수, 주스 이름을 위한 텍스트 구성 가능한 함수, 주스 설명을 위한 구성 가능한 함수를 추가합니다.
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.text.font.FontWeight
@Composable
fun JuiceDetails(juice: Juice, modifier: Modifier = Modifier) {
Column(modifier, verticalArrangement = Arrangement.Top) {
Text(
text = juice.name,
style = MaterialTheme.typography.h5.copy(fontWeight = FontWeight.Bold),
)
Text(juice.description)
RatingDisplay(rating = juice.rating, modifier = Modifier.padding(top = 8.dp))
}
}
- 해결되지 않은 참조 오류를 해결하려면 구성 가능한 함수
RatingDisplay()
를 만듭니다.
뷰 시스템에는 다음과 같은 평점 막대를 표시하는 RatingBar
가 있습니다. Compose에는 평점 막대 컴포저블 함수가 없으므로 처음부터 이 요소를 구현해야 합니다.
- 평점에 따라 별표를 표시하도록
RatingDisplay()
함수를 정의합니다. 이 구성 가능한 함수는 평점에 따라 별표 수를 표시합니다.
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.pluralStringResource
@Composable
fun RatingDisplay(rating: Int, modifier: Modifier = Modifier) {
val displayDescription = pluralStringResource(R.plurals.number_of_stars, count = rating)
Row(
// Content description is added here to support accessibility
modifier.semantics {
contentDescription = displayDescription
}
) {
repeat(rating) {
// Star [contentDescription] is null as the image is for illustrative purpose
Image(
modifier = Modifier.size(32.dp),
painter = painterResource(R.drawable.star),
contentDescription = null
)
}
}
}
Compose에서 별표 드로어블을 만들려면 별표 벡터 애셋을 만들어야 합니다.
- Project 창에서 drawable > New > Vector Asset을 마우스 오른쪽 버튼으로 클릭합니다.
- Asset Studio 대화상자에서 별표 아이콘을 검색합니다. 색이 채워진 별표 아이콘을 선택합니다.
- 별표의 색상 값을 625B71로 변경합니다.
- Next > Finish를 클릭합니다.
- 드로어블이
res/drawable
폴더에 나타납니다.
- 미리보기 컴포저블 함수를 추가하여
JuiceDetails
컴포저블 함수를 미리 봅니다.
@Preview
@Composable
fun PreviewJuiceDetails() {
JuiceDetails(Juice(1, "Sweet Beet", "Apple, carrot, beet, and lemon", "Red", 4))
}
삭제 버튼 구성 가능한 함수 만들기
JuiceListAdapter.kt
에서 람다 콜백 함수와 수정자를 사용하는 또 다른 구성 가능한 함수DeleteButton()
을 추가합니다.- 다음 코드와 같이 람다를
onClick
인수로 설정하고Icon()
을 전달합니다.
import androidx.compose.ui.res.painterResource
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@Composable
fun DeleteButton(onDelete: () -> Unit, modifier: Modifier = Modifier) {
IconButton(
onClick = { onDelete() },
modifier = modifier
) {
Icon(
painter = painterResource(R.drawable.ic_delete),
contentDescription = stringResource(R.string.delete)
)
}
}
- 삭제 버튼을 미리 보는 미리보기 함수를 추가합니다.
@Preview
@Composable
fun PreviewDeleteIcon() {
DeleteButton({})
}
5. ListItem 함수 구현
이제 목록 항목을 표시하는 데 필요한 모든 컴포저블이 있으므로 이를 레이아웃에서 정렬할 수 있습니다. 이전 단계에서 정의한 ListItem()
함수를 확인합니다.
@Composable
fun ListItem(
input: Juice,
onEdit: (Juice) -> Unit,
onDelete: (Juice) -> Unit,
modifier: Modifier = Modifier
) {
}
JuiceListAdapter.kt
에서 다음 단계를 완료하여 ListItem()
함수를 구현합니다.
Mdc3Theme {}
람다 내에Row
레이아웃을 추가합니다.
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import com.google.accompanist.themeadapter.material3.Mdc3Theme
Mdc3Theme {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.SpaceBetween
) {
}
}
Row
람다 내에서 하위 요소로 만든 세 가지 구성 가능한 함수JuiceIcon
,JuiceDetails
,DeleteButton
을 호출합니다.
JuiceIcon(input.color)
JuiceDetails(input, Modifier.weight(1f))
DeleteButton({})
Modifier.
weight
(1f)
를 JuiceDetails()
컴포저블에 전달하면 비가중 하위 요소를 측정한 후 남은 가로 공간을 주스 세부정보가 차지합니다.
- 상단 정렬을 사용하여
onDelete(input)
람다 및 수정자를DeleteButton
컴포저블에 매개변수로 전달합니다.
DeleteButton(
onDelete = {
onDelete(input)
},
modifier = Modifier.align(Alignment.Top)
)
- 구성 가능한 함수
ListItem
을 미리 보는 미리보기 함수를 작성합니다.
@Preview
@Composable
fun PreviewListItem() {
ListItem(Juice(1, "Sweet Beet", "Apple, carrot, beet, and lemon", "Red", 4), {})
}
- 구성 가능한 함수
ListItem
을 뷰 홀더에 바인딩합니다. 목록 항목을 클릭하면 수정 대화상자가 열리도록clickable()
람다 함수 내에서onEdit(input)
을 호출합니다.
JuiceListViewHolder
클래스의 bind()
함수 내에서 구성 가능한 함수를 호스팅해야 합니다. setContent
메서드를 사용하여 Compose UI 콘텐츠를 호스팅할 수 있는 Android 뷰인 ComposeView
를 사용합니다.
fun bind(input: Juice) {
composeView.setContent {
ListItem(
input,
onDelete,
modifier = Modifier
.fillMaxWidth()
.clickable {
onEdit(input)
}
.padding(vertical = 8.dp, horizontal = 16.dp),
)
}
}
- 앱을 실행합니다. 좋아하는 주스를 추가합니다. 빛나는 Compose 목록 항목을 확인하세요.
.
축하합니다. 뷰 기반 앱에서 Compose 요소를 사용하는 첫 번째 Compose 상호 운용성 앱을 만들었습니다.
6. 솔루션 코드 가져오기
완료된 Codelab의 코드를 다운로드하려면 다음 git 명령어를 사용하면 됩니다.
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-juice-tracker.git $ cd basic-android-kotlin-compose-training-juice-tracker $ git checkout views-with-compose
또는 ZIP 파일로 저장소를 다운로드한 다음 압축을 풀고 Android 스튜디오에서 열어도 됩니다.
솔루션 코드를 보려면 GitHub에서 확인하세요.
7. 자세히 알아보기
Android 개발자 문서
- Compose용 도구 | Jetpack Compose | Android 개발자
- 상호 운용성 API | Jetpack Compose | Android 개발자
- 이전 전략 | Jetpack Compose | Android 개발자
Codelab [중급]