MDC-102 Android: マテリアルの構造とレイアウト(Kotlin)

1. はじめに

logo_components_color_2x_web_96dp.png

マテリアル コンポーネント(MDC)は、デベロッパーがマテリアル デザインを実装する際に役立ちます。Google のエンジニアと UX デザイナーのチームが作成した MDC には、美しく機能的な UI コンポーネントが多数含まれており、Android、iOS、ウェブ、Flutter.material.io/develop に利用可能です。

Codelab MDC-101 では、テキスト フィールドとインクのさざ波が付いたボタンという 2 つのマテリアル コンポーネント(MDC)を使用して、ログインページを作成しました。今度は、この基礎にナビゲーション、構造、データを追加していきましょう。

作成するアプリの概要

この Codelab では、衣類と生活雑貨を販売する e コマースアプリ Shrine のホーム画面を作成します。これには次のものが含まれます。

  • トップ アプリバー
  • 商品が並んだグリッドリスト

249db074eff043f4.png

この Codelab の MDC-Android コンポーネント

  • AppBarLayout
  • MaterialCardView

必要なもの

  • Android 開発に関する基本的な知識
  • Android Studio(まだお持ちでない場合はこちらからダウンロードしてください)
  • Android Emulator または Android デバイス(Android Studio から入手可能)
  • サンプルコード(次の手順を参照)

Android アプリの作成経験はどの程度ありますか?

<ph type="x-smartling-placeholder"></ph> 初心者 中級 上達 をご覧ください。

2. 開発環境を設定する

MDC-101 から続行する場合

MDC-101 を完了していれば、コードはこの Codelab 用に準備されています。ステップ 3(トップ アプリバーを追加する)に進みます。

ゼロから始める

Codelab のスターター アプリをダウンロードする

スターター アプリは material-components-android-codelabs-102-starter/kotlin ディレクトリにあります。開始する前に、そのディレクトリへの cd を行ってください。

GitHub からクローンを作成する

GitHub からこの Codelab のクローンを作成するには、次のコマンドを実行します。

git clone https://github.com/material-components/material-components-android-codelabs
cd material-components-android-codelabs/
git checkout 102-starter

Android Studio にスターター コードを読み込む

  1. 設定ウィザードが完了し、[Welcome to Android Studio] ウィンドウが表示されたら、[Open an existing Android Studio project] をクリックします。サンプルコードをインストールしたディレクトリに移動し、kotlin ->Shrine(またはパソコンで「shrine」を検索)して、Shipping プロジェクトを開きます。
  2. Android Studio がプロジェクトをビルドして同期するまで待ちます。進捗状況は、Android Studio ウィンドウ下部のアクティビティ インジケーターに表示されます。
  3. この時点では、Android SDK やビルドツール(以下に示すものなど)が不足しているため、Android Studio でビルドエラーが発生する場合があります。Android Studio の手順に沿って、これらをインストールまたは更新し、プロジェクトを同期します。

KzoYWC1S7Se7yL8igi1vXF_mbVxAdl2lg5kb7RODrsVpEng0G6U3NK1Qnn0faBBZd2u71yMXioy9tD-7fv3NXvVO4N3EtMMeWDTmqBMMl6egd9R5uXX0T_SKmahbmRor3wZZHX0ByA

プロジェクトの依存関係を追加する

プロジェクトに MDC Android サポート ライブラリへの依存関係が必要である。ダウンロードしたサンプルコードには、この依存関係がすでにリストされているはずですが、次の手順で確認することをおすすめします。

  1. app モジュールの build.gradle ファイルに移動し、dependencies ブロックに MDC Android への依存関係が含まれていることを確認します。
api 'com.google.android.material:material:1.1.0-alpha06'
  1. (省略可)必要に応じて build.gradle ファイルを編集して次の依存関係を追加し、プロジェクトを同期します。
dependencies {
    api 'com.google.android.material:material:1.1.0-alpha06'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.android.volley:volley:1.1.1'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21"
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:core:1.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test:runner:1.2.0-alpha05'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha05'
}

スターター アプリを実行する

  1. [Run / Play] ボタンの左側のビルド構成が app であることを確認します。
  2. 緑色の [Run / Play] ボタンを押して、アプリをビルドし実行します。
  3. [Select Deployment Target] ウィンドウで、利用可能なデバイスの一覧にすでに Android デバイスが表示されている場合は、ステップ 8 に進みます。それ以外の場合は、[Create New Virtual Device] をクリックします。
  4. [Select Hardware] 画面で [Pixel 2] などのスマートフォン デバイスを選択し、[Next] をクリックします。
  5. [System Image] 画面で、最新の Android バージョン(可能であれば API レベルが最も高いもの)を選択します。インストールされていない場合は、表示される [Download] をクリックして、ダウンロードを完了します。
  6. [Next] をクリックします。
  7. [Android Virtual Device (AVD)] 画面で、設定をそのままにして [Finish] をクリックします。
  8. デプロイ ターゲット ダイアログで [Android デバイス] を選択します。
  9. [OK] をクリックします。
  10. Android Studio によってアプリがビルドおよびデプロイされ、対象デバイスでそのアプリが自動的に開きます。

完了しました。MDC-101 Codelab で作成した Shrine のログインページが表示されます。

4cb0c218948144b4.png

ログイン画面が正常に表示されるようになったので、アプリにいくつかのプロダクトを追加しましょう。

3. トップ アプリバーを追加する

ログインページを閉じるとホーム画面が表示され、「完了」というメッセージが画面に表示されます。ここまでは問題ないのですが、今のところユーザーは何もできず、アプリ内のどこにいるのかわからない状態です。そこで、ナビゲーションを追加します。

マテリアル デザインには、高度なユーザビリティを実現するナビゲーション パターンがあります。特に目立つコンポーネントの 1 つが、トップ アプリバーです。

ナビゲーションを提供し、ユーザーが他のアクションにすばやくアクセスできるように、トップ アプリバーを追加しましょう。

AppBar ウィジェットを追加する

shr_product_grid_fragment.xml で、「You Did it!」を含む <LinearLayout> ブロックを削除します。TextView に置き換え、次のように置き換えます。

shr_product_grid_fragment.xml

<com.google.android.material.appbar.AppBarLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content">

   <androidx.appcompat.widget.Toolbar
       android:id="@+id/app_bar"
       style="@style/Widget.Shrine.Toolbar"
       android:layout_width="match_parent"
       android:layout_height="?attr/actionBarSize"
       app:title="@string/shr_app_name" />
</com.google.android.material.appbar.AppBarLayout>

shr_product_grid_fragment.xml は次のようになります。

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

アプリバーは多くの場合、タイトルの横にボタンがあります。メニュー アイコンを追加しましょう。

ナビゲーション アイコンを追加する

引き続き shr_product_grid_fragment.xml で、レイアウトに追加した Toolbar XML コンポーネントに以下を追加します。

shr_product_grid_fragment.xml

app:navigationIcon="@drawable/shr_menu"

shr_product_grid_fragment.xml は次のようになります。

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">
  
   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>
  
</FrameLayout>

操作ボタンを追加し、トップ アプリバーのスタイルを設定する

アプリバーの端にボタンを追加することもできます。Android では、これらは操作ボタンと呼ばれます。トップ アプリバーのスタイルを設定し、そのメニューにアクション ボタンを追加します。

ProductGridFragment.ktonCreateView 関数で、setSupportActionBar を使用して、ActionBar として使用されるように activityToolbar を設定します。これは、inflater でビューを作成した後に行うことができます。

ProductGridFragment.kt

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   // Inflate the layout for this fragment with the ProductGrid theme
   val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

   // Set up the toolbar.
   (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

   return view;
}

次に、先ほどツールバーを設定するために変更したメソッドの直下で、onCreateOptionsMenu をオーバーライドして shr_toolbar_menu.xml のコンテンツをツールバーにインフレートします。

ProductGridFragment.kt

override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
   super.onCreateOptionsMenu(menu, menuInflater)
}

最後に、ProductGridFragment.ktonCreate() をオーバーライドし、super() を呼び出した後に true を使用して setHasOptionMenu を呼び出します。

ProductGridFragment.kt

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   setHasOptionsMenu(true)
}

上記のコード スニペットでは、XML レイアウトのアプリバーをこのアクティビティのアクションバーとして設定しています。コールバック onCreateOptionsMenu は、メニューとして何を使用するかをアクティビティに伝えます。この例では、R.menu.shr_toolbar_menu のメニュー項目がアプリバーに配置されます。メニュー ファイルには「Search」という 2 つの項目が含まれています。[フィルタ]をクリックします

shr_toolbar_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item
       android:id="@+id/search"
       android:icon="@drawable/shr_search"
       android:title="@string/shr_search_title"
       app:showAsAction="always" />
   <item
       android:id="@+id/filter"
       android:icon="@drawable/shr_filter"
       android:title="@string/shr_filter_title"
       app:showAsAction="always" />
</menu>

これらの変更後、ProductGridFragment.kt ファイルは次のようになります。

ProductGridFragment.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*

class ProductGridFragment : Fragment() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setHasOptionsMenu(true)
   }

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment with the ProductGrid theme
       val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

       // Set up the tool bar
       (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

       return view;
   }

   override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
       super.onCreateOptionsMenu(menu, menuInflater)
   }
}

ビルドして実行します。ホーム画面は次のようになります。

d04e8aa3b27f4754.png

ツールバーにナビゲーション アイコンとタイトルが配置され、右側に 2 つのアクション アイコンが表示されるようになりました。また、ツールバーでは、コンテンツとは異なるレイヤ上にあるように微妙な影をつけて、エレベーションを表示します。

4. カードを追加する

アプリの構造ができたので、次はコンテンツをカードに配置して整理しましょう。

カードを追加する

まずは、トップ アプリバーの下にカードを 1 つ追加しましょう。カードには、画像用の領域、タイトル、付随するテキストのラベルが必要です。shr_product_grid_fragment.xmlAppBarLayout の下に以下を追加します。

shr_product_grid_fragment.xml

<com.google.android.material.card.MaterialCardView
   android:layout_width="160dp"
   android:layout_height="180dp"
   android:layout_marginBottom="16dp"
   android:layout_marginLeft="16dp"
   android:layout_marginRight="16dp"
   android:layout_marginTop="70dp"
   app:cardBackgroundColor="?attr/colorPrimaryDark"
   app:cardCornerRadius="4dp">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_gravity="bottom"
       android:background="#FFFFFF"
       android:orientation="vertical"
       android:padding="8dp">

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_title"
           android:textAppearance="?attr/textAppearanceHeadline6" />

       <TextView
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:padding="2dp"
           android:text="@string/shr_product_description"
           android:textAppearance="?attr/textAppearanceBody2" />
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

ビルドして実行します。

f6184a55ccb5f920.png

このプレビューでは、カードが左端からインセットされており、角が丸く、影(カードのエレベーション)があります。その要素全体を「コンテナ」と呼びます。コンテナを除き、コンテナ内の要素はすべて省略可能です。

コンテナには、ヘッダー テキスト、サムネイルまたはアバター、小見出し、分割線、さらにはボタンやアイコンといった要素を追加できます。たとえば、先ほど作成したカードでは、LinearLayout 内に 2 つの TextView(1 つはタイトル用、もう 1 つはセカンダリ テキスト用)をカードの下に配置しています。

カードは通常、他のカードと一緒にコレクションで表示されます。この Codelab の次のセクションでは、それらをコレクションとしてグリッドに配置します。

5. カードのグリッドを作成する

複数のカードが画面に表示されている場合は、1 つ以上のコレクションにグループ化されます。グリッド内のカードは同一平面上にあるため、互いに同じ静止高度を共有します(カードを選択またはドラッグしない限り、この Codelab では扱いません)。

カードのグリッドを設定する

用意されている shr_product_card.xml ファイルを見てみましょう。

shr_product_card.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   app:cardBackgroundColor="@android:color/white"
   app:cardElevation="2dp"
   app:cardPreventCornerOverlap="true">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       <com.android.volley.toolbox.NetworkImageView
           android:id="@+id/product_image"
           android:layout_width="match_parent"
           android:layout_height="@dimen/shr_product_card_image_height"
           android:background="?attr/colorPrimaryDark"
           android:scaleType="centerCrop" />

       <LinearLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:padding="16dp">

           <TextView
               android:id="@+id/product_title"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_title"
               android:textAppearance="?attr/textAppearanceHeadline6" />

           <TextView
               android:id="@+id/product_price"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:text="@string/shr_product_description"
               android:textAppearance="?attr/textAppearanceBody2" />
       </LinearLayout>
   </LinearLayout>
</com.google.android.material.card.MaterialCardView>

このカード レイアウトには、画像 1 枚のカード(この場合は、URL から画像を読み込んで表示できる NetworkImageView)と 2 つの TextViews が含まれています。

次に、用意されている ProductCardRecyclerViewAdapter を確認します。これは、ProductGridFragment と同じパッケージにあります。

ProductCardRecyclerViewAdapter.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView

import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry

/**
* Adapter used to show a simple grid of products.
*/
class ProductCardRecyclerViewAdapter(private val productList: List<ProductEntry>) : RecyclerView.Adapter<ProductCardViewHolder>() {

   override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductCardViewHolder {
       val layoutView = LayoutInflater.from(parent.context).inflate(R.layout.shr_product_card, parent, false)
       return ProductCardViewHolder(layoutView)
   }

   override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

   override fun getItemCount(): Int {
       return productList.size
   }
}

上記のアダプタクラスは、グリッドのコンテンツを管理します。各ビューが特定のコンテンツに対して行う動作を決定するために、まもなく onBindViewHolder() のコードを記述します。

同じパッケージで ProductCardViewHolder を見ることもできます。このクラスはカード レイアウトに影響を与えるビューを格納しているため、後で変更できます。

ProductCardViewHolder.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.View
import androidx.recyclerview.widget.RecyclerView

class ProductCardViewHolder(itemView: View) //TODO: Find and store views from itemView
   : RecyclerView.ViewHolder(itemView)

グリッドをセットアップするには、まず shr_product_grid_fragment.xml からプレースホルダ MaterialCardView を削除します。次に、カードのグリッドを表すコンポーネントを追加します。ここでは、RecyclerView を使用します。RecyclerView コンポーネントを、AppBarLayout XML コンポーネントの下の shr_product_grid_fragment.xml に追加します。

shr_product_grid_fragment.xml

<androidx.core.widget.NestedScrollView
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_marginTop="56dp"
   android:background="@color/productGridBackgroundColor"
   android:paddingStart="@dimen/shr_product_grid_spacing"
   android:paddingEnd="@dimen/shr_product_grid_spacing"
   app:layout_behavior="@string/appbar_scrolling_view_behavior">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recycler_view"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

</androidx.core.widget.NestedScrollView>

shr_product_grid_fragment.xml は次のようになります。

shr_product_grid_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".ProductGridFragment">

   <com.google.android.material.appbar.AppBarLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <androidx.appcompat.widget.Toolbar
           android:id="@+id/app_bar"
           style="@style/Widget.Shrine.Toolbar"
           android:layout_width="match_parent"
           android:layout_height="?attr/actionBarSize"
           app:navigationIcon="@drawable/shr_menu"
           app:title="@string/shr_app_name" />
   </com.google.android.material.appbar.AppBarLayout>

   <androidx.core.widget.NestedScrollView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginTop="56dp"
       android:background="@color/productGridBackgroundColor"
       android:paddingStart="@dimen/shr_product_grid_spacing"
       android:paddingEnd="@dimen/shr_product_grid_spacing"
       app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <androidx.recyclerview.widget.RecyclerView
           android:id="@+id/recycler_view"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

   </androidx.core.widget.NestedScrollView>

</FrameLayout>

最後に、onCreateView() で、setUpToolbar(view) を呼び出した後で return ステートメントの前に、ProductGridFragment.ktRecyclerView 初期化コードを追加します。

ProductGridFragment.kt

override fun onCreateView(
       inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
   // Inflate the layout for this fragment with the ProductGrid theme
   val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

   // Set up the toolbar.
   (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

   // Set up the RecyclerView
   view.recycler_view.setHasFixedSize(true)
   view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
   val adapter = ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(resources))
   view.recycler_view.adapter = adapter
   val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
   val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
   view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))

   return view;
}

上記のコード スニペットには、RecyclerView を設定するために必要な初期化ステップが含まれています。これには、RecyclerView のレイアウト マネージャーの設定、RecyclerView のアダプターの初期化と設定が含まれます。

ProductGridFragment.kt ファイルは次のようになります。

ProductGridFragment .kt

package com.google.codelabs.mdc.kotlin.shrine

import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.codelabs.mdc.kotlin.shrine.network.ProductEntry
import kotlinx.android.synthetic.main.shr_product_grid_fragment.view.*

class ProductGridFragment : Fragment() {

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setHasOptionsMenu(true)
   }

   override fun onCreateView(
           inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
       // Inflate the layout for this fragment with the ProductGrid theme
       val view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false)

       // Set up the toolbar.
       (activity as AppCompatActivity).setSupportActionBar(view.app_bar)

       // Set up the RecyclerView
       view.recycler_view.setHasFixedSize(true)
       view.recycler_view.layoutManager = GridLayoutManager(context, 2, RecyclerView.VERTICAL, false)
       val adapter = ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(resources))
       view.recycler_view.adapter = adapter
       val largePadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing)
       val smallPadding = resources.getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small)
       view.recycler_view.addItemDecoration(ProductGridItemDecoration(largePadding, smallPadding))

       return view;
   }

   override fun onCreateOptionsMenu(menu: Menu, menuInflater: MenuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu)
       super.onCreateOptionsMenu(menu, menuInflater)
   }
}

ビルドして実行します。

f9aeab846fc3bb4c.png

カードが手に入りました。まだ何も表示されていないので、商品データを追加しましょう。

画像とテキストを追加する

カードごとに、画像、商品名、価格を追加します。ViewHolder 抽象化は各カードのビューを保持します。ViewHolder で、次のように 3 つのビューを追加します。

ProductCardViewHolder.kt

package com.google.codelabs.mdc.kotlin.shrine

import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

import com.android.volley.toolbox.NetworkImageView

class ProductCardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

   var productImage: NetworkImageView = itemView.findViewById(R.id.product_image)
   var productTitle: TextView = itemView.findViewById(R.id.product_title)
   var productPrice: TextView = itemView.findViewById(R.id.product_price)
}

以下のように、ProductCardRecyclerViewAdapteronBindViewHolder() メソッドを更新して、各商品ビューのタイトル、価格、商品画像を設定します。

ProductCardRecyclerViewAdapter.kt

override fun onBindViewHolder(holder: ProductCardViewHolder, position: Int) {
   if (position < productList.size) {
       val product = productList[position]
       holder.productTitle.text = product.title
       holder.productPrice.text = product.price
       ImageRequester.setImageFromUrl(holder.productImage, product.url)
   }
}

上記のコードは、ViewHolder を使用して、RecyclerView のアダプターに各カードをどのように処理するかを指示しています。

ここでは、ViewHolderTextView ごとにテキストデータを設定し、ImageRequester を呼び出して URL から画像を取得します。ImageRequester は、便宜上 Google が提供しているクラスであり、Volley ライブラリを使用します(これについてはこの Codelab の範囲外ですが、ご自身でコードを見てもかまいません)。

ビルドして実行します。

249db074eff043f4.png

当社の製品がアプリに表示されるようになりました!

6. まとめ

アプリに、ログイン画面からホーム画面に移動して商品を表示する基本的なフローができました。わずか数行のコードで、タイトルと 3 つのボタンを含むトップ アプリバーと、アプリのコンテンツを表示するカードのグリッドを追加しました。ホーム画面は、基本的な構造と実用的なコンテンツを備えた、シンプルかつ機能的なものになりました。

次のステップ

上部のアプリバー、カード、テキスト フィールド、ボタンには、MDC-Android ライブラリの 4 つのコア マテリアル デザイン コンポーネントを使用しました。その他のコンポーネントについては、MDC-Android カタログをご覧ください。

アプリは完全に機能しますが、特定のブランドやスタイルはまだ表現されていません。MDC-103: 色、形状、高度、タイプによるマテリアル デザインのテーマ設定では、これらのコンポーネントのスタイルをカスタマイズして、鮮やかでモダンなブランドを表現します。

この Codelab を完了するためにそれなりの時間と労力を必要とした

非常にそう思う そう思う どちらとも言えない そう思わない まったくそう思わない

今後もマテリアル コンポーネントを使用したい

<ph type="x-smartling-placeholder"></ph> 非常にそう思う そう思う どちらとも言えない そう思わない まったくそう思わない をご覧ください。