カードを使用して画像の一覧を表示する

1. 始める前に

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

7ac81c2a9a79365b.png

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

8d7a20a5d7a079ce.png

前提条件

  • アプリに画像リソースを追加できる。
  • XML レイアウトの変更に慣れている。
  • RecyclerView にテキストのリストを表示するアプリを作成できる。
  • RecyclerView のアダプターを作成できる。

学習内容

  • RecyclerView に表示されているアファメーションのリストに画像を追加する方法。
  • RecyclerView アイテム レイアウトで MaterialCardView を使用する方法。
  • UI を視覚的に変更して、より洗練されたアプリにする方法。

作成するアプリの概要

  • RecyclerView を使用してカードのリストを表示する、洗練された Affirmations アプリ。各カードには画像とアファメーション テキストが含まれています。

必要なもの

  • Android Studio バージョン 4.1 以上がインストールされているパソコン。
  • 画像ファイルをダウンロードできるインターネット接続環境。
  • 前の「Affirmations アプリを作成する」Codelab での Affirmations アプリ(スターター コードは提供されません。アプリの作成が前提です)。

2. リストアイテムに画像を追加する

ここまでの作業により、RecyclerView にアファメーション文字列を表示するアダプター ItemAdapter を作成できました。機能性は優れていますが、視覚的には魅力がありません。このタスクでは、リストアイテムのレイアウトとアダプターのコードを変更して、アファメーションとともに画像を表示します。

画像をダウンロードする

  1. まず、Android Studio で、前の Codelab で作成した Affirmations アプリ プロジェクトを開きます。このプロジェクトがない場合は、前の Codelab の手順に沿ってプロジェクトを作成してから、この Codelab に戻ってきてください。
  2. 次に、パソコンに画像ファイルをダウンロードします。アプリのアファメーションごとに 1 枚ずつ、合計 10 枚の画像が必要です。ファイル名は image1.jpg から image10.jpg にする必要があります。
  3. この画像をパソコンから Android Studio のプロジェクトの [res] > [drawable] フォルダ(app/src/main/res/drawable)にコピーします。このリソースをアプリに追加すると、コードからリソース ID(R.drawable.image1 など)を使用して上記画像にアクセスできるようになります(画像を特定するために Android Studio のコードを再ビルドしなければならない場合があります)。

これで、アプリで画像を使用できるようになります。

Affirmation クラスの画像のサポートを追加する

このステップでは、Affirmation データクラスに、画像リソース ID の値を保持するためのプロパティを追加します。これにより、単一の Affirmation オブジェクト インスタンスに、アファメーション テキスト用のリソース ID と、アファメーション画像のリソース ID が含まれることになります。

  1. model パッケージ内の Affirmation.kt ファイルを開きます。
  2. imageResourceId という名前の別の Int パラメータを追加して、Affirmation クラスのコンストラクタを変更します。

リソース アノテーションの使用

stringResourceIdimageResourceId はどちらも整数値です。これは問題ないように見えますが、呼び出し元が間違った順序で引数を渡してしまう可能性があります(stringResourceId ではなく imageResourceId を最初に渡す)。

これを回避するには、リソース アノテーションを使用します。アノテーションは、クラス、メソッド、パラメータに追加情報を加えることができるので便利です。アノテーションは常に @ 記号で宣言されます。この場合、@StringRes アノテーションを文字列リソース ID プロパティに追加し、@DrawableRes アノテーションをドローアブル リソース ID プロパティに追加します。その場合、リソース ID の種類を間違って指定した場合に警告が表示されます。

  1. @StringRes アノテーションを stringResourceId に追加します。
  2. @DrawableRes アノテーションを imageResourceId に追加します。
  3. インポート androidx.annotation.DrawableResandroidx.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 を渡します。

  1. Datasource.kt を開きます。Affirmation のインスタンス化ごとにエラーが表示されます。
  2. 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 つのビュー(TextViewImageView)があるため、これを ViewGroup 内の子ビューとして配置します。ビューを垂直方向に並べるには、LinearLayout を使用します。LinearLayout は、すべての子ビューを垂直または水平の一方向に揃えます。

a5cb4349a970c992.png

  1. [res] > [layout] > [list_item.xml] を開きます。既存の TextView の周りに LinearLayout を追加し、orientation プロパティを vertical に設定します。
  2. 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>
  1. LinearLayout, 内で、TextView, の前にリソース ID が item_image である ImageView を追加します。
  2. ImageView の幅を match_parent に、高さを 194dp に設定します。画面サイズに応じて、この値では常に数枚のカードが画面に表示されることになります。
  3. scaleTypecenterCrop. に設定します。
  4. 画像は装飾に使用されるため、importantForAccessibility 属性を no に設定します。
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="194dp"
        android:id="@+id/item_image"
        android:importantForAccessibility="no"
        android:scaleType="centerCrop" />

ItemAdapter を更新して画像を設定する

  1. adapter/ItemAdapter.kt[app] > [java] > [adapter] > [ItemAdapter])を開きます。
  2. ItemViewHolder クラスに移動します。
  3. ItemViewHolder インスタンスは、リストアイテムのレイアウトで TextView への参照と ImageView への参照を保持する必要があります。以下のように変更します。

textView プロパティの初期化の下に、imageView という名前の val を追加します。findViewById() を使用して ID が item_imageImageView への参照を見つけ、それを 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)
}
  1. ItemAdapteronBindViewHolder() 関数を見つけます。
  2. これまでは、アファメーションの stringResourceIdItemViewHoldertextView に設定していました。ここで、アファメーション アイテムの 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)
    }
  1. アプリを実行し、アファメーションのリストをスクロールします。

485d002900657409.png

画像があるとアプリは格段にきれいに見えます。しかし、アプリの UI にはまだ改善の余地があります。次のセクションでは、UI を改善するためにアプリを微調整します。

3. UI の改良

ここまでで、アファメーション文字列と画像のリストで構成された機能的なアプリを作りました。このセクションでは、コードと XML を少し変更するだけで、アプリをさらに洗練されたものにする方法をご紹介します。

パディングの追加

まず、リスト内のアイテムの間に空白を追加します。

  1. item_list.xml[app] > [res] > [layout] > [item_list.xml])を開いて、既存の LinearLayout16dp パディングを追加します。

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">
  1. item_title TextView16dp パディングを追加します。
  2. 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" />
  1. アプリを実行してみてください。リストの見栄えが良くなったと思いますか?

a95304a44a8876d7.png

カードを使用する

画像がその画像の上または下にあるアファメーション テキストに属しているかどうかを判断するのはまだ難しい状態です。これを解決するには、カード ビューを使用します。カードビューを使用すると、コンテナのスタイルを維持しながら、簡単にビューグループを追加できます。カードの使用に関するマテリアル デザインの詳細については、こちらのカードについてのガイドをご覧ください。

  1. 既存の LinearLayout の周囲に MaterialCardView を追加します。
  2. もう一度、スキーマ宣言を LinearLayout から MaterialCardView に移動します。
  3. MaterialCardViewlayout_widthmatch_parent に、layout_heightwrap_content に設定します。
  4. 8dplayout_margin を追加します。
  5. LinearLayout のパディングを削除して、空白が多すぎないようにします。
  6. アプリをもう一度実行します。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>

af61b5d2baa66e39.png

アプリのテーマカラーを変更する

アプリのデフォルトのテーマカラーは、他の選択肢に比べて落ち着かない場合があります。このタスクでは、アプリのテーマカラーを青色に変更します。後で、自分のアイデアでまた変更できます。

こちらのリンクから、マテリアル デザインのカラーパレットから事前定義された青の色合いをご確認いただけます。

この Codelab では、以下のマテリアル デザイン パレットの色を使用します。

  • blue_200: #FF90CAF9
  • blue_500: #FF2196F3
  • blue_700: #FF1976D2

カラーリソースを追加する

アプリ内で使用する色を colors.xml ファイルという一元的な場所で定義します。

  1. colors.xml を開きます([res] > [color] > [colors.xml])。
  2. 次のように定義した青色の新しいカラーリソースをファイルに追加します。
<color name="blue_200">#FF90CAF9</color>
<color name="blue_500">#FF2196F3</color>
<color name="blue_700">#FF1976D2</color>

テーマカラーを変更する

新しいカラーリソースが作成されたので、テーマで使用できるようになりました。

  1. themes.xml を開きます([res] > [values] > [themes] > [themes.xml])。
  2. <!-- Primary brand color. --> セクションを見つけます。
  3. @color/blue_500 を使用するように colorPrimary を追加または変更します。
  4. @color/blue_700 を使用するように colorPrimaryVariant を追加または変更します。
<item name="colorPrimary">@color/blue_500</item>
<item name="colorPrimaryVariant">@color/blue_700</item>
  1. アプリを実行すると、アプリバーの色が青色に変わります。

8d7a20a5d7a079ce.png

ダークテーマ カラーを更新する

アプリのダークテーマには、より彩度の低い色を設定することをおすすめします。

  1. ダークテーマの themes.xml ファイルを開きます([themes] > [themes.xml (night)])。
  2. テーマ属性 colorPrimarycolorPrimaryVariant を以下のように追加または変更します。
<item name="colorPrimary">@color/blue_200</item>
<item name="colorPrimaryVariant">@color/blue_500</item>
  1. アプリを実行します。
  2. デバイスの [設定] で [ダークテーマ] をオンにします。

  1. アプリがダークテーマに切り替わります。下のスクリーンショットのようになっていることを確認してください。

6564b21429206ebc.png

  1. この時点で、colors.xml ファイルで未使用の色を削除することもできます(たとえば、デフォルトのアプリテーマで使用されている紫のカラーリソースなど)。

アプリアイコンを変更する

最後のステップとして、アプリアイコンを更新します。

  1. アプリアイコン ファイル ic_launcher_foreground.xmlic_launcher_background.xml をダウンロードします。ブラウザがファイルをダウンロードせずに表示する場合は、[File] > [Save Page As...] の順に選択し、ファイルをパソコンに保存します。
  2. Android Studio で「drawable/ic_launcher_background.xml」と「drawable-v24/ic_launcher_foreground.xml」の 2 つのファイルを削除します。これらは前のアプリアイコン用です。[Safe delete (with usage search)] チェックボックスをオフにできます。
  3. 次に、[res] > [drawable] フォルダを右クリックして、[New] > [Image Asset] を選択します。

51e40f30078ad631.png

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

8c437aa925887439.png

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

ddac89ef587fba99.png

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

c0c1986d1887afdb.png

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

649133c325fa9b17.png

  1. 最後に、プロジェクト内の Kotlin ファイルと XML ファイルを再フォーマットすることを忘れないでください。そうすれば、コードがすっきりして、スタイル ガイドラインに沿ったものになります。

これで、すばらしい Affirmations アプリが出来上がりました。

Android アプリでデータの一覧を表示する方法を把握したうえで、次は何を作ればいいのでしょうか。

4. 解答コード

Affirmations アプリの解答コードは、下記の GitHub リポジトリにあります。

  1. プロジェクト用に提供されている GitHub リポジトリ ページに移動します。
  2. ブランチ名が Codelab で指定されたブランチ名と一致していることを確認します。たとえば、次のスクリーンショットでは、ブランチ名は main です。

1e4c0d2c081a8fd2.png

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

1debcf330fd04c7b.png

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

Android Studio でプロジェクトを開く

  1. Android Studio を起動します。
  2. [Welcome to Android Studio] ウィンドウで、[Open] をクリックします。

d8e9dbdeafe9038a.png

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

8d1fda7396afe8e5.png

  1. ファイル ブラウザで、展開したプロジェクト フォルダがある場所([ダウンロード] フォルダなど)に移動します。
  2. そのプロジェクト フォルダをダブルクリックします。
  3. Android Studio でプロジェクトが開かれるまで待ちます。
  4. 実行ボタン 8de56cba7583251f.png をクリックして、アプリをビルドし、実行します。期待どおりにビルドされることを確認します。

5. まとめ

  • RecyclerView で追加コンテンツを表示するには、基になるデータモデル クラスとデータソースを変更します。次に、リストアイテムのレイアウトとアダプターを更新して、そのデータをビューに設定します。
  • リソース アノテーションを使用して、適切なタイプのリソース ID がクラスのコンストラクタに渡されるようにします。
  • Android 向けマテリアル コンポーネントのライブラリを使用することで、推奨のマテリアル デザインのガイドラインに沿ったアプリをより簡単に作成できます。
  • マテリアル カードにコンテンツを表示するには、MaterialCardView を使用します。
  • 色や間隔など、アプリの視覚的な微調整を行うことで、アプリがより洗練され、一貫性のあるものになります。

6. 関連リンク

7. チャレンジ タスク

このシリーズの Codelab では、RecyclerViewLinearLayoutManager を使用することを学習しました。RecyclerView では、各種 LayoutManager を使用して、データをさまざまにレイアウトできます。

  • RecyclerViewlayoutManager プロパティを GridLayoutManager に変更します。
  • 列数を 3 に変更します。
  • アダプターのレイアウトを変更して、データをグリッドで表示します。