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 に変更します。
- アダプターのレイアウトを変更して、データをグリッドで表示します。