1. 始める前に
前の Codelab では、RecyclerView 内にテキストのリストを表示する Affirmations アプリを作成しました。

フォローアップとなるこの Codelab では、アプリのアファメーションごとに想像をかき立てる画像を追加します。Android ライブラリのマテリアル コンポーネントの MaterialCardView ウィジェットを使用して、カード内のアファメーションごとにテキストと画像を表示します。その後、UI を洗練させてアプリを完成させ、より統一感のある美しいユーザー エクスペリエンスを実現させます。完成したアプリは次のスクリーンショットのようになります。

前提条件
- アプリに画像リソースを追加できる。
- XML レイアウトの変更に慣れている。
- RecyclerViewにテキストのリストを表示するアプリを作成できる。
- RecyclerViewのアダプターを作成できる。
学習内容
- RecyclerViewに表示されているアファメーションのリストに画像を追加する方法。
- RecyclerViewアイテム レイアウトで- MaterialCardViewを使用する方法。
- UI を視覚的に変更して、より洗練されたアプリにする方法。
作成するアプリの概要
- RecyclerViewを使用してカードのリストを表示する、洗練された Affirmations アプリ。各カードには画像とアファメーション テキストが含まれています。
必要なもの
- Android Studio バージョン 4.1 以上がインストールされているパソコン。
- 画像ファイルをダウンロードできるインターネット接続環境。
- 前の「Affirmations アプリを作成する」Codelab での Affirmations アプリ(スターター コードは提供されません。アプリの作成が前提です)。
2. リストアイテムに画像を追加する
ここまでの作業により、RecyclerView にアファメーション文字列を表示するアダプター ItemAdapter を作成できました。機能性は優れていますが、視覚的には魅力がありません。このタスクでは、リストアイテムのレイアウトとアダプターのコードを変更して、アファメーションとともに画像を表示します。
画像をダウンロードする
- まず、Android Studio で、前の Codelab で作成した Affirmations アプリ プロジェクトを開きます。このプロジェクトがない場合は、前の Codelab の手順に沿ってプロジェクトを作成してから、この Codelab に戻ってきてください。
- 次に、パソコンに画像ファイルをダウンロードします。アプリのアファメーションごとに 1 枚ずつ、合計 10 枚の画像が必要です。ファイル名は image1.jpgからimage10.jpgにする必要があります。
- この画像をパソコンから Android Studio のプロジェクトの [res] > [drawable] フォルダ(app/src/main/res/drawable)にコピーします。このリソースをアプリに追加すると、コードからリソース ID(R.drawable.image1など)を使用して上記画像にアクセスできるようになります(画像を特定するために Android Studio のコードを再ビルドしなければならない場合があります)。
これで、アプリで画像を使用できるようになります。
Affirmation クラスの画像のサポートを追加する
このステップでは、Affirmation データクラスに、画像リソース ID の値を保持するためのプロパティを追加します。これにより、単一の Affirmation オブジェクト インスタンスに、アファメーション テキスト用のリソース ID と、アファメーション画像のリソース ID が含まれることになります。
- modelパッケージ内の- Affirmation.ktファイルを開きます。
- imageResourceIdという名前の別の- Intパラメータを追加して、- Affirmationクラスのコンストラクタを変更します。
リソース アノテーションの使用
stringResourceId と imageResourceId はどちらも整数値です。これは問題ないように見えますが、呼び出し元が間違った順序で引数を渡してしまう可能性があります(stringResourceId ではなく imageResourceId を最初に渡す)。
これを回避するには、リソース アノテーションを使用します。アノテーションは、クラス、メソッド、パラメータに追加情報を加えることができるので便利です。アノテーションは常に @ 記号で宣言されます。この場合、@StringRes アノテーションを文字列リソース ID プロパティに追加し、@DrawableRes アノテーションをドローアブル リソース ID プロパティに追加します。その場合、リソース ID の種類を間違って指定した場合に警告が表示されます。
- @StringResアノテーションを- stringResourceIdに追加します。
- @DrawableResアノテーションを- imageResourceIdに追加します。
- インポート androidx.annotation.DrawableResとandroidx.annotation.StringResがパッケージ宣言の後、ファイルの先頭に追加されていることを確認します。
Affirmation.kt
package com.example.affirmations.model
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
data class Affirmation(
   @StringRes val stringResourceId: Int,
   @DrawableRes val imageResourceId: Int
)
画像を使用してアファメーション リストを初期化する
Affirmation クラスのコンストラクタを変更したので、Datasource クラスを更新する必要があります。初期化された各 Affirmation オブジェクトに画像リソース ID を渡します。
- Datasource.ktを開きます。- Affirmationのインスタンス化ごとにエラーが表示されます。
- Affirmationごとに、- R.drawable.image1などの画像リソース ID を引数として追加します。
Datasource.kt
package com.example.affirmations.data
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)
        )
    }
}
ImageView をリストアイテムのレイアウトに追加する
リストの各アファメーションに画像を表示するには、アイテムのレイアウトに ImageView を追加する必要があります。現在、2 つのビュー(TextView と ImageView)があるため、これを ViewGroup 内の子ビューとして配置します。ビューを垂直方向に並べるには、LinearLayout を使用します。LinearLayout は、すべての子ビューを垂直または水平の一方向に揃えます。

- [res] > [layout] > [list_item.xml] を開きます。既存の TextViewの周りにLinearLayoutを追加し、orientationプロパティをverticalに設定します。
- xmlns schema宣言行を- TextView要素から- LinearLayout要素に移動すると、エラーが解消されます。
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>
- LinearLayout,内で、- TextView,の前にリソース ID が- item_imageである- ImageViewを追加します。
- ImageViewの幅を- match_parentに、高さを- 194dpに設定します。画面サイズに応じて、この値では常に数枚のカードが画面に表示されることになります。
- scaleTypeを- centerCrop.に設定します。
- 画像は装飾に使用されるため、importantForAccessibility属性をnoに設定します。
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="194dp"
        android:id="@+id/item_image"
        android:importantForAccessibility="no"
        android:scaleType="centerCrop" />
ItemAdapter を更新して画像を設定する
- adapter/ItemAdapter.kt([app] > [java] > [adapter] > [ItemAdapter])を開きます。
- ItemViewHolderクラスに移動します。
- ItemViewHolderインスタンスは、リストアイテムのレイアウトで- TextViewへの参照と- ImageViewへの参照を保持する必要があります。以下のように変更します。
textView プロパティの初期化の下に、imageView という名前の val を追加します。findViewById() を使用して ID が item_image の ImageView への参照を見つけ、それを imageView プロパティに代入します。
ItemAdapter.kt
class ItemViewHolder(private val view: View): RecyclerView.ViewHolder(view) {
    val textView: TextView = view.findViewById(R.id.item_title)
    val imageView: ImageView = view.findViewById(R.id.item_image)
}
- ItemAdapterで- onBindViewHolder()関数を見つけます。
- これまでは、アファメーションの stringResourceIdをItemViewHolderのtextViewに設定していました。ここで、アファメーション アイテムのimageResourceIdをリストアイテム ビューのImageViewに設定します。
    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = dataset[position]
        holder.textView.text = context.resources.getString(item.stringResourceId)
        holder.imageView.setImageResource(item.imageResourceId)
    }
- アプリを実行し、アファメーションのリストをスクロールします。

画像があるとアプリは格段にきれいに見えます。しかし、アプリの UI にはまだ改善の余地があります。次のセクションでは、UI を改善するためにアプリを微調整します。
3. UI の改良
ここまでで、アファメーション文字列と画像のリストで構成された機能的なアプリを作りました。このセクションでは、コードと XML を少し変更するだけで、アプリをさらに洗練されたものにする方法をご紹介します。
パディングの追加
まず、リスト内のアイテムの間に空白を追加します。
- item_list.xml([app] > [res] > [layout] > [item_list.xml])を開いて、既存の- LinearLayoutに- 16dpパディングを追加します。
list_item.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="16dp">
- item_title- TextViewに- 16dpパディングを追加します。
- TextViewで、- textAppearance属性を- ?attr/textAppearanceHeadline6に設定します。- textAppearanceは、テキスト固有のスタイル設定を定義できる属性です。その他の定義済みのテキスト外観に関する値については、こちらの共通テーマ属性に関するブログ記事の TextAppearance セクションをご覧ください。
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:textAppearance="?attr/textAppearanceHeadline6" />
- アプリを実行してみてください。リストの見栄えが良くなったと思いますか?

カードを使用する
画像がその画像の上または下にあるアファメーション テキストに属しているかどうかを判断するのはまだ難しい状態です。これを解決するには、カード ビューを使用します。カードビューを使用すると、コンテナのスタイルを維持しながら、簡単にビューグループを追加できます。カードの使用に関するマテリアル デザインの詳細については、こちらのカードについてのガイドをご覧ください。
- 既存の LinearLayoutの周囲にMaterialCardViewを追加します。
- もう一度、スキーマ宣言を LinearLayoutからMaterialCardViewに移動します。
- MaterialCardViewの- layout_widthを- match_parentに、- layout_heightを- wrap_contentに設定します。
- 8dpの- layout_marginを追加します。
- LinearLayoutのパディングを削除して、空白が多すぎないようにします。
- アプリをもう一度実行します。MaterialCardViewによって、各アファメーションがより区別しやすくなったでしょうか。
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <ImageView
            android:id="@+id/item_image"
            android:layout_width="match_parent"
            android:layout_height="194dp"
            android:importantForAccessibility="no"
            android:scaleType="centerCrop" />
        <TextView
            android:id="@+id/item_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="16dp"
            android:textAppearance="?attr/textAppearanceHeadline6" />
    </LinearLayout>
</com.google.android.material.card.MaterialCardView>

アプリのテーマカラーを変更する
アプリのデフォルトのテーマカラーは、他の選択肢に比べて落ち着かない場合があります。このタスクでは、アプリのテーマカラーを青色に変更します。後で、自分のアイデアでまた変更できます。
こちらのリンクから、マテリアル デザインのカラーパレットから事前定義された青の色合いをご確認いただけます。
この Codelab では、以下のマテリアル デザイン パレットの色を使用します。
- blue_200: #FF90CAF9
- blue_500: #FF2196F3
- blue_700: #FF1976D2
カラーリソースを追加する
アプリ内で使用する色を colors.xml ファイルという一元的な場所で定義します。
- colors.xmlを開きます([res] > [color] > [colors.xml])。
- 次のように定義した青色の新しいカラーリソースをファイルに追加します。
<color name="blue_200">#FF90CAF9</color>
<color name="blue_500">#FF2196F3</color>
<color name="blue_700">#FF1976D2</color>
テーマカラーを変更する
新しいカラーリソースが作成されたので、テーマで使用できるようになりました。
- themes.xmlを開きます([res] > [values] > [themes] > [themes.xml])。
- <!-- Primary brand color. -->セクションを見つけます。
- @color/blue_500を使用するように- colorPrimaryを追加または変更します。
- @color/blue_700を使用するように- colorPrimaryVariantを追加または変更します。
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item>
- アプリを実行すると、アプリバーの色が青色に変わります。
ダークテーマ カラーを更新する
アプリのダークテーマには、より彩度の低い色を設定することをおすすめします。
- ダークテーマの themes.xmlファイルを開きます([themes] > [themes.xml (night)])。
- テーマ属性 colorPrimaryとcolorPrimaryVariantを以下のように追加または変更します。
<item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_500</item>
- アプリを実行します。
- デバイスの [設定] で [ダークテーマ] をオンにします。
| 
 | 
 | 
- アプリがダークテーマに切り替わります。下のスクリーンショットのようになっていることを確認してください。

- この時点で、colors.xmlファイルで未使用の色を削除することもできます(たとえば、デフォルトのアプリテーマで使用されている紫のカラーリソースなど)。
アプリアイコンを変更する
最後のステップとして、アプリアイコンを更新します。
- アプリアイコン ファイル ic_launcher_foreground.xmlとic_launcher_background.xmlをダウンロードします。ブラウザがファイルをダウンロードせずに表示する場合は、[File] > [Save Page As...] の順に選択し、ファイルをパソコンに保存します。
- Android Studio で「drawable/ic_launcher_background.xml」と「drawable-v24/ic_launcher_foreground.xml」の 2 つのファイルを削除します。これらは前のアプリアイコン用です。[Safe delete (with usage search)] チェックボックスをオフにできます。
- 次に、[res] > [drawable] フォルダを右クリックして、[New] > [Image Asset] を選択します。

- [Configure Image Asset] ウィンドウで [Foreground layer] が選択されていることを確認します。

- その下にある [Path] ラベルを見つけます。
- [Path] テキスト ボックス内のフォルダ アイコンをクリックします。
- パソコンにダウンロードした ic_launcher_foreground.xmlファイルを見つけて開きます。

- [Background Layer] タブに切り替えます。
- [Path] テキスト ボックス内の [Browse] アイコンをクリックします。
- パソコンで ic_launcher_background.xmlファイルを見つけて開きます。その他の変更は必要ありません。
- [Next] をクリックします。

- [Confirm Icon Path] ダイアログで [Finish] をクリックします。既存のアイコンを上書きしても問題ありません。
- おすすめの方法として、新しいベクター型ドローアブルの ic_launcher_foreground.xmlとic_launcher_background.xmlを、drawable-anydpi-v26という新しいリソース ディレクトリに移動できます。アダプティブ アイコンは API 26 で導入されたため、このリソースは API 26 以降を搭載したデバイスでのみ使用されます(どの dpi にも対応)。
- drawable-v24ディレクトリに何も残っていない場合は削除します。
- アプリを実行すると、新たに美しいアプリアイコンがアプリドロワーに表示されます。

- 最後に、プロジェクト内の Kotlin ファイルと XML ファイルを再フォーマットすることを忘れないでください。そうすれば、コードがすっきりして、スタイル ガイドラインに沿ったものになります。
これで、すばらしい Affirmations アプリが出来上がりました。
| 
 | 
 | 
Android アプリでデータの一覧を表示する方法を把握したうえで、次は何を作ればいいのでしょうか。
4. 解答コード
Affirmations アプリの解答コードは、下記の GitHub リポジトリにあります。
- プロジェクト用に提供されている GitHub リポジトリ ページに移動します。
- ブランチ名が Codelab で指定されたブランチ名と一致していることを確認します。たとえば、次のスクリーンショットでは、ブランチ名は main です。

- プロジェクトの GitHub ページで、[Code] ボタンをクリックすると、ポップアップが表示されます。

- ポップアップで、[Download ZIP] をクリックして、プロジェクトをパソコンに保存します。ダウンロードが完了するまで待ちます。
- パソコンに保存したファイルを見つけます([ダウンロード] フォルダなど)。
- ZIP ファイルをダブルクリックして展開します。プロジェクト ファイルが入った新しいフォルダが作成されます。
Android Studio でプロジェクトを開く
- Android Studio を起動します。
- [Welcome to Android Studio] ウィンドウで、[Open] をクリックします。

注: Android Studio がすでに開いている場合は、メニューから [File] > [Open] を選択します。

- ファイル ブラウザで、展開したプロジェクト フォルダがある場所([ダウンロード] フォルダなど)に移動します。
- そのプロジェクト フォルダをダブルクリックします。
- Android Studio でプロジェクトが開かれるまで待ちます。
- 実行ボタン  をクリックして、アプリをビルドし、実行します。期待どおりにビルドされることを確認します。 をクリックして、アプリをビルドし、実行します。期待どおりにビルドされることを確認します。
5. まとめ
- RecyclerViewで追加コンテンツを表示するには、基になるデータモデル クラスとデータソースを変更します。次に、リストアイテムのレイアウトとアダプターを更新して、そのデータをビューに設定します。
- リソース アノテーションを使用して、適切なタイプのリソース ID がクラスのコンストラクタに渡されるようにします。
- Android 向けマテリアル コンポーネントのライブラリを使用することで、推奨のマテリアル デザインのガイドラインに沿ったアプリをより簡単に作成できます。
- マテリアル カードにコンテンツを表示するには、MaterialCardViewを使用します。
- 色や間隔など、アプリの視覚的な微調整を行うことで、アプリがより洗練され、一貫性のあるものになります。
6. 関連リンク
7. チャレンジ タスク
このシリーズの Codelab では、RecyclerView で LinearLayoutManager を使用することを学習しました。RecyclerView では、各種 LayoutManager を使用して、データをさまざまにレイアウトできます。
- RecyclerViewの- layoutManagerプロパティを- GridLayoutManagerに変更します。
- 列数を 3 に変更します。
- アダプターのレイアウトを変更して、データをグリッドで表示します。
 
  

