1. 始める前に
Jetpack Compose は、当初から View の相互運用性を考慮して設計されており、Compose と View システムはリソースを共有し、互いに連携しながら UI を表示することができます。この機能により、Compose を既存のビューベースのアプリに追加することができるようになっています。つまり、アプリ全体が完全に Compose ベースになるまで、Compose と View をコードベース内で共存させることができるのです。
この Codelab では、Juice Tracker アプリのビューベースのリストアイテムを Compose に変更します。残りの Juice Tracker のビューは、必要に応じて自分で変換できます。
ビューベースの UI を備えたアプリがある場合、その UI 全体を一度に書き換えたくはないでしょう。この Codelab では、ビューベースの UI の中の 1 つのビューを 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 と View は特定の画面で共存できます。一部の UI 要素を Compose に、残りを View システムに保持できます。たとえば、Compose はリストのみとし、画面の残りの部分は View システムに保持できます。
以下の手順で、Compose ライブラリを Juice Tracker アプリに追加します。
- Android Studio で Juice Tracker を開きます。
- アプリレベルの
build.gradle.kts
を開きます。 buildFeatures
ブロック内にcompose = true
フラグを追加します。
buildFeatures {
//...
// Enable Jetpack Compose for this module
compose = true
}
このフラグにより、Android Studio が Compose を扱えるようになります。前の Codelab ではこのステップを実施していません。これは、新しい Android Studio Compose テンプレート プロジェクトを作成するときに、このコードが Android Studio によって自動的に生成されるためです。
buildFeatures
で、composeOptions
ブロックを追加します。- ブロック内で、
kotlinCompilerExtensionVersion
を"1.5.1"
に設定して Kotlin コンパイラ バージョンを設定します。
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
dependencies
セクションで、Compose の依存関係を追加します。Compose をビューベースのアプリに追加するには、次の依存関係が必要です。これらの依存関係は、Compose とアクティビティとの統合、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 View です。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
と、リストアイテムの編集と削除を行うための 2 つのコールバック関数を受け取ります。
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
) {
}
作成するリストアイテムのプレビューを確認します。ジュース アイコン、ジュースの詳細、削除ボタンのアイコンがあります。これらのコンポーネントは後ほど実装します。
Juice アイコンのコンポーザブルを作成する
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
変数を使用して、ユーザー選択に関連付けられたカラーリソースを取得します。
- 2 つのアイコン
ic_juice_color
とic_juice_clear
を重ねて表示するBox
レイアウトを追加します。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
に、ジュースの詳細を表示する別のコンポーズ可能な関数を追加する必要があります。また、名前と説明用の 2 つの 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()
というコンポーズ可能な関数を作成します。
View システムには、次の評価バーを表示する 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
で、ラムダ コールバック関数と Modifier を受け取る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
ラムダ内で、子要素として作成した 3 つのコンポーザブル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 View である 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 Studio で開くこともできます。
解答コードを確認する場合は、GitHub で表示します。
7. 関連リンク
Android デベロッパー ドキュメント
- Compose のツール | Jetpack Compose | Android デベロッパー
- 相互運用 API | Jetpack Compose | Android デベロッパー
- 移行戦略 | Jetpack Compose | Android デベロッパー
Codelab [中級]