1. 始める前に
この Codelab では、Jetpack Compose を使用してアプリでスクロール可能なリストを作成する方法を学びます。
アファメーションのリストを日常をポジティブにする美しい画像とともに表示する Affirmations アプリを取り扱います。
データはすでに用意されているので、そのデータを取得して UI に表示するだけです。
前提条件
- Kotlin のリストに精通していること
- Jetpack Compose でレイアウトを作成した経験
- デバイスまたはエミュレータでアプリを実行した経験
学習内容
- Jetpack Compose を使用してマテリアル デザイン カードを作成する方法
- Jetpack Compose を使用してスクロール可能なリストを作成する方法
作成するアプリの概要
- 既存のアプリケーションをベースとして、UI にスクロール可能なリストを追加する
最終的なプロダクトは次のようになります。
必要なもの
- インターネットにアクセスできるパソコン、ウェブブラウザ、Android Studio
- GitHub へのアクセス
スターター コードをダウンロードする
Android Studio で basic-android-kotlin-compose-training-affirmations
フォルダを開きます。
アプリが starter
ブランチコードからビルドされた場合、空白の画面を表示することが想定されています。
2. リストアイテムのデータクラスを作成する
アファメーション用のデータクラスを作成する
Android アプリでは、リストはリストアイテムで構成されます。単一のデータを持つリストアイテムの場合、これは文字列や整数などの単純なアイテムになります。画像とテキストなど、複数のデータを持つリストアイテムの場合、それらすべてのプロパティを格納するクラスが必要になります。データクラスはプロパティのみを格納するクラスの一種で、このようなプロパティを扱うユーティリティ メソッドを提供します。
- com.example.affirmations の下に新しいパッケージを作成します。
新しいパッケージに model という名前を付けます。この model パッケージには、データクラスで表されるデータモデルが含まれます。このデータクラスは、「アファメーション」となるものに関連する情報を表すプロパティで構成されます。アファメーションは、文字列リソースと画像リソースを 1 つずつ含みます。パッケージとは、クラスと他のディレクトリを含むディレクトリのことです。
- com.example.affirmations.model パッケージ内に新しいクラスを作成します。
新しいクラスに Affirmation という名前を付け、これを Data Class にします。
- 各
Affirmation
は、1 つの画像と 1 つの文字列で構成されます。Affirmation
データクラスに 2 つのval
プロパティを作成します。一つはstringResourceId
、もう一つはimageResourceId
という名前にします。どちらも整数にする必要があります。
Affirmation.kt
data class Affirmation(
val stringResourceId: Int,
val imageResourceId: Int
)
stringResourceId
プロパティに@StringRes
アノテーションを付け、imageResourceId
に@DrawableRes
アノテーションを付けます。stringResourceId
は、文字列リソースに格納されているアファメーション テキストの ID を表します。imageResourceId
は、ドローアブル リソースに格納されているアファメーション画像の ID を表します。
Affirmation.kt
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
data class Affirmation(
@StringRes val stringResourceId: Int,
@DrawableRes val imageResourceId: Int
)
- com.example.affirmations.data パッケージで Datasource.kt ファイルを開き、2 つの import ステートメントと
Datasource
クラスのコンテンツのコメント化を解除します。
Datasource.kt
import com.example.affirmations.R
import com.example.affirmations.model.Affirmation
class Datasource() {
fun loadAffirmations(): List<Affirmation> {
return listOf<Affirmation>(
Affirmation(R.string.affirmation1, R.drawable.image1),
Affirmation(R.string.affirmation2, R.drawable.image2),
Affirmation(R.string.affirmation3, R.drawable.image3),
Affirmation(R.string.affirmation4, R.drawable.image4),
Affirmation(R.string.affirmation5, R.drawable.image5),
Affirmation(R.string.affirmation6, R.drawable.image6),
Affirmation(R.string.affirmation7, R.drawable.image7),
Affirmation(R.string.affirmation8, R.drawable.image8),
Affirmation(R.string.affirmation9, R.drawable.image9),
Affirmation(R.string.affirmation10, R.drawable.image10))
}
}
3. アプリにリストを追加する
リストアイテム カードを作成する
このアプリはアファメーションのリストを表示することを想定しています。リストを表示するための UI を構成する最初のステップとして、リストアイテムを作成します。各アファメーション アイテムは 1 つの画像と 1 つの文字列で構成されます。これらの各アイテムのデータにはスターター コードが付属しています。このようなアイテムを表示するために、UI コンポーネントを作成します。
アイテムは、Image
コンポーザブルと Text
コンポーザブルを含む Card
コンポーザブルで構成されます。Compose における Card
は、コンテンツとアクションを単一のコンテナで表示するサーフェスです。プレビューで、アファメーション カードは次のようになります。
カードには、画像と、その下にテキストが表示されます。この縦型のレイアウトは、Card
コンポーザブルでラップされた Column
コンポーザブルを使用することで実現できます。自分で試してみるか、以下の手順に沿って作成してください。
- MainActivity.kt ファイルを開きます。
AffirmationsApp()
メソッドの下にAffirmationCard()
という新しいメソッドを作成し、@Composable
アノテーションを付けます。
MainActivity.kt
@Composable
fun AffirmationsApp() {
}
@Composable
fun AffirmationCard() {
}
- メソッド シグネチャを編集して、
Affirmation
オブジェクトをパラメータとして取得します。Affirmation
オブジェクトはmodel
パッケージのものです。
MainActivity.kt
import com.example.affirmations.model.Affirmation
@Composable
fun AffirmationCard(affirmation: Affirmation) {
}
- 署名に
modifier
パラメータを追加します。パラメータのデフォルト値Modifier
を設定します。
MainActivity.kt
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
}
AffirmationCard
メソッド内で、Card
コンポーザブルを呼び出します。modifier
パラメータを渡します。
MainActivity.kt
import androidx.compose.material3.Card
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier) {
}
}
Card
コンポーザブル内にColumn
コンポーザブルを追加します。Column
コンポーザブル内のアイテムは、UI 上で縦方向に配置されます。これで、関連するテキストの上に画像を配置できます。逆に、Row
コンポーザブル内のアイテムは横方向に配置されます。
MainActivity.kt
import androidx.compose.foundation.layout.Column
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier) {
Column {
}
}
}
Image
コンポーザブルをColumn
コンポーザブルのラムダ本文内に追加します。Image
コンポーザブルには、表示するリソースとcontentDescription
が常に必要です。リソースは、painter
パラメータに渡されるpainterResource
である必要があります。painterResource
メソッドは、ベクター型ドローアブルか、PNG などのラスター化されたアセット形式を読み込みます。また、contentDescription
パラメータとしてstringResource
を渡します。
MainActivity.kt
import androidx.compose.foundation.Image
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
)
}
}
}
painter
パラメータとcontentDescription
パラメータに加えて、modifier
とcontentScale
を渡します。contentScale
は、画像の拡大方法と表示方法を決定します。Modifier
オブジェクトのfillMaxWidth
属性を設定して、高さを194.dp
にする必要があります。contentScale
は、ContentScale.Crop
である必要があります。
MainActivity.kt
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.ui.unit.dp
import androidx.compose.ui.layout.ContentScale
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
modifier = Modifier
.fillMaxWidth()
.height(194.dp),
contentScale = ContentScale.Crop
)
}
}
}
Column
内で、Image
コンポーザブルの後にText
コンポーザブルを作成します。affirmation.stringResourceId
のstringResource
をtext
パラメータに渡し、padding
属性を16.dp
に設定したModifier
オブジェクトを渡します。また、MaterialTheme.typography.headlineSmall
をstyle
パラメータに渡してテキストテーマを設定します。
MainActivity.kt
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.platform.LocalContext
@Composable
fun AffirmationCard(affirmation: Affirmation, modifier: Modifier = Modifier) {
Card(modifier = modifier) {
Column {
Image(
painter = painterResource(affirmation.imageResourceId),
contentDescription = stringResource(affirmation.stringResourceId),
modifier = Modifier
.fillMaxWidth()
.height(194.dp),
contentScale = ContentScale.Crop
)
Text(
text = LocalContext.current.getString(affirmation.stringResourceId),
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.headlineSmall
)
}
}
}
AffirmationCard コンポーザブルのプレビュー
Affirmations アプリの UI の中核となるカードを作成することができました。カードが正しく表示されることを確認するために、アプリ全体を起動せずにプレビューできるコンポーザブルを作成します。
AffirmationCardPreview()
という名前のプライベート メソッドを作成します。メソッドに@Preview
と@Composable
のアノテーションを付けます。
MainActivity.kt
import androidx.compose.ui.tooling.preview.Preview
@Preview
@Composable
private fun AffirmationCardPreview() {
}
- メソッド内で
AffirmationCard
コンポーザブルを呼び出します。そのコンポーザブルに、コンストラクタに渡されたR.string.affirmation1
文字列リソースとR.drawable.image1
ドローアブル リソースを使用する新しいAffirmation
オブジェクトを渡します。
MainActivity.kt
@Preview
@Composable
private fun AffirmationCardPreview() {
AffirmationCard(Affirmation(R.string.affirmation1, R.drawable.image1))
}
- [Split] タブを開くと、
AffirmationCard
のプレビューが表示されます。必要に応じて、[Design] ペインで [Build & Refresh] をクリックしてプレビューを表示します。
リストを作成する
リストアイテムのコンポーネントがリストの唯一のビルディング ブロックです。リストアイテムを作成したら、それを利用してリスト コンポーネントそのものを作成できます。
AffirmationList()
という関数を作成し、@Composable
アノテーションを付けて、Affirmation
オブジェクトのList
をメソッド シグネチャのパラメータとして宣言します。
MainActivity.kt
@Composable
fun AffirmationList(affirmationList: List<Affirmation>) {
}
- デフォルト値を
Modifier
にして、メソッド シグネチャのパラメータとしてmodifier
オブジェクトを宣言します。
MainActivity.kt
@Composable
fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
}
- Jetpack Compose では、
LazyColumn
コンポーザブルを使用してスクロール可能なリストを作成できます。LazyColumn
とColumn
の違いは、表示するアイテム数が少ない場合はColumn
を使用する必要がある点です(Compose は一度にすべてのアイテムを読み込むため)。Column
には、事前に定義した(つまり一定の)数のコンポーザブルのみを格納できます。LazyColumn
はオンデマンドでコンテンツを追加できるため、長いリスト、特にリストの長さが不明な場合に適しています。LazyColumn
もデフォルトでスクロール機能を提供します。追加のコードは必要ありません。AffirmationList()
関数内でLazyColumn
コンポーザブルを宣言します。modifier
オブジェクトを引数としてLazyColumn
に渡します。
MainActivity.kt
import androidx.compose.foundation.lazy.LazyColumn
@Composable
fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier) {
}
}
LazyColumn
のラムダ本体で、items()
メソッドを呼び出してaffirmationList
を渡します。items()
メソッドは、アイテムをLazyColumn
に追加するためのものです。このメソッドは、このコンポーザブルに固有のもので、他のコンポーザブルでは一般的ではありません。
MainActivity.kt
import androidx.compose.foundation.lazy.items
@Composable
fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier) {
items(affirmationList) {
}
}
}
items()
メソッドの呼び出しにはラムダ関数が必要です。この関数で、affirmationList
の 1 つのアファメーション アイテムを表すaffirmation
のパラメータを指定します。
MainActivity.kt
@Composable
fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier) {
items(affirmationList) { affirmation ->
}
}
}
- リスト内のアファメーションごとに
AffirmationCard()
コンポーザブルを呼び出します。affirmation
と、padding
属性を8.dp
に設定したModifier
オブジェクトを渡します。
MainActivity.kt
@Composable
fun AffirmationList(affirmationList: List<Affirmation>, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier) {
items(affirmationList) { affirmation ->
AffirmationCard(
affirmation = affirmation,
modifier = Modifier.padding(8.dp)
)
}
}
}
リストを表示する
AffirmationsApp
コンポーザブルで、現在のレイアウトの向きを取得し、変数に保存します。これらは、後でパディングを設定するために使用されます。
MainActivity.kt
import com.example.affirmations.data.Datasource
@Composable
fun AffirmationsApp() {
val layoutDirection = LocalLayoutDirection.current
}
- 次に、
Surface
コンポーザブルを作成します。このコンポーザブルは、AffirmationsList
コンポーザブルのパディングを設定します。
MainActivity.kt
import com.example.affirmations.data.Datasource
@Composable
fun AffirmationsApp() {
val layoutDirection = LocalLayoutDirection.current
Surface() {
}
}
- 親の最大幅と最大高さを埋め、ステータスバーのパディングを設定し、左右のパディングを
layoutDirection
に設定するModifier
をSurface
コンポーザブルに渡します。たとえば、LayoutDirection
オブジェクトをパディングに変換する場合は、WindowInsets.safeDrawing.asPaddingValues().calculateStartPadding(layoutDirection)
のようにします。
MainActivity.kt
import com.example.affirmations.data.Datasource
@Composable
fun AffirmationsApp() {
val layoutDirection = LocalLayoutDirection.current
Surface(
Modifier = Modifier
.fillMaxSize()
.statusBarsPadding()
.padding(
start = WindowInsets.safeDrawing.asPaddingValues()
.calculateStartPadding(layoutDirection),
end = WindowInsets.safeDrawing.asPaddingValues()
.calculateEndPadding(layoutDirection),
),
) {
}
}
Surface
コンポーザブルのラムダで、AffirmationList
コンポーザブルを呼び出し、DataSource().loadAffirmations()
をaffirmationList
パラメータに渡します。
MainActivity.kt
import com.example.affirmations.data.Datasource
@Composable
fun AffirmationsApp() {
val layoutDirection = LocalLayoutDirection.current
Surface(
Modifier = Modifier
.fillMaxSize()
.statusBarsPadding()
.padding(
start = WindowInsets.safeDrawing.asPaddingValues()
.calculateStartPadding(layoutDirection),
end = WindowInsets.safeDrawing.asPaddingValues()
.calculateEndPadding(layoutDirection),
),
) {
AffirmationsList(
affirmationList = Datasource().loadAffirmations(),
)
}
}
デバイスまたはエミュレータで Affirmations アプリを実行すると、完成したプロダクトが表示されます。
4. 解答コードを取得する
この Codelab の完成したコードをダウンロードするには、以下の git コマンドを使用します。
$ git clone https://github.com/google-developer-training/basic-android-kotlin-compose-training-affirmations.git $ cd basic-android-kotlin-compose-training-affirmations $ git checkout intermediate
または、リポジトリを ZIP ファイルとしてダウンロードし、Android Studio で開くこともできます。
解答コードを確認する場合は、GitHub で表示します。
5. おわりに
ここでは、Jetpack Compose でカード、リストアイテム、スクロール可能なリストを作成する方法を学習しました。これらはあくまでリスト作成の基本ツールであり、リストアイテムは、創造性を発揮して自由にカスタマイズできます。
まとめ
-
Card
コンポーザブルを使用してリストアイテムを作成します。 Card
コンポーザブル内の UI を変更します。-
LazyColumn
コンポーザブルを使用してスクロール可能なリストを作成します。 - カスタムのリストアイテムを使用してリストを作成します。