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

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 のホーム画面を作成します。これには次のものが含まれます。

  • トップ アプリバー
  • 商品のグリッドリスト

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

  • AppBarLayout
  • MaterialCardView

必要なもの

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

Android アプリ作成のご経験についてお答えください。

初心者 中級者 上級者

MDC-101 から続行する場合

MDC-101 が完了済みであれば、コードはこの Codelab を進められる状態になっています。ステップ 3(トップ アプリバーを追加する)に進みます。

ゼロから始める

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

スターター アプリをダウンロード

スターター アプリは material-components-android-codelabs-102-starter/java ディレクトリにあります。開始する前に、必ずこのディレクトリに 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] をクリックします。サンプルコードをインストールしたディレクトリに移動し、[java -> Shrine](またはパソコンで「shrine」を検索)を選択すると、Shrine プロジェクトが開きます。
  2. Android Studio がプロジェクトをビルドして同期するまで待ちます。進捗状況は、Android Studio ウィンドウ下部のアクティビティ インジケーターに表示されます。
  3. この時点では、Android SDK やビルドツール(以下に示すものなど)が不足しているため、Android Studio でビルドエラーが発生する場合があります。Android Studio の指示に従って、それをインストール/更新して、プロジェクトを同期してください。

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

プロジェクトに 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 のログインページが表示されます。

ログイン画面が正常に表示されたので、アプリに商品を追加しましょう。

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

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

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

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

shr_product_grid_fragment.xml で、&ut; を含む <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 では、これを操作ボタンと呼びます。

プログラムでトップ アプリバーのスタイルを設定し、メニューに操作ボタンを追加します。

まず、ツールバーをセットアップするメソッドを作成します。このメソッドは、id を使用してツールバーへの参照を取得し、getActivity() を使用してアクティビティへの参照も取得します。アクティビティが null でない場合は、setSupportActionBar を使用して ToolbarActionBar として設定します。

ProductGridFragment.java

private void setUpToolbar(View view) {
   Toolbar toolbar = view.findViewById(R.id.app_bar);
   AppCompatActivity activity = (AppCompatActivity) getActivity();
   if (activity != null) {
       activity.setSupportActionBar(toolbar);
   }
}

次に、先ほど追加した setUpToolbar メソッドの直下で onCreateOptionsMenu をオーバーライドして、shr_toolbar_menu.xml の内容をツールバーにインフレートします。

ProductGridFragment.java

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
   menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
   super.onCreateOptionsMenu(menu, menuInflater);
}

次に、onCreateView() メソッドの内容に追加した setUpToolbar メソッドの呼び出しを次のように追加します。

ProductGridFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   // Inflate the layout for this fragment with the ProductGrid theme
   View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

   // Set up the toolbar
   setUpToolbar(view);

   return view;
}

最後に、ProductGridFragment.javaonCreate() メソッドを追加します。メソッド本体で、setHasOptionMenu のパラメータを true に設定します。

メソッドは次のようになります。

ProductGridFragment.java

@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setHasOptionsMenu(true);
}

上記のコードでは、XML レイアウトのアプリバーをこのアクティビティのアクションバーとして設定しています。コールバック onCreateOptionsMenu は、メニューとして使用する内容をアクティビティに指示します。今回は、R.menu.shr_toolbar_menu のメニュー項目がアプリバーに配置されます。

メニュー ファイルには、「検索」と「フィルタ」の 2 つの項目が含まれます。

shr_bar_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.java ファイルは次のようになります。

ProductGridFragment.java

package com.google.codelabs.mdc.java.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 android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;


public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }
  
   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       return view;
   }
  
   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

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

これで、ツールバーにナビゲーション アイコン、タイトル、2 つのアクション アイコンが右側に表示されます。また、ツールバーには、コンテンツとは別のレイヤに微妙な影が付けられてエレベーションが表示されます。

アプリの構造がある程度できたので、コンテンツをカードに入れて整理しましょう。

カードを追加

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

shr_product_grid_fragment.xml で、AppBarLayout の下に次のコードを追加します。

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>

ビルドして実行します。

このプレビューでは、カードが画面の左端から挿入され、角が丸く、影が描かれています(これはカードの高度を表します)。エリア全体を「コンテナ」と呼びます。コンテナ自体はもちろん、コンテナ内の要素はすべてオプションです。

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

カードは通常、他のカードと一緒にコレクションで表示されます。この Codelab の次のセクションでは、コレクションとしてグリッド形式でレイアウトします。

複数のカードが画面に表示されている場合は、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>

このカード レイアウトには、画像(ここでは URL の画像を含めることができる NetworkImageView)と 2 つの TextViews が含まれています。

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

ProductCardRecyclerViewAdapter.java

package com.google.codelabs.mdc.java.shrine;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.codelabs.mdc.java.shrine.network.ImageRequester;
import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

import java.util.List;

/**
* Adapter used to show a simple grid of products.
*/
public class ProductCardRecyclerViewAdapter extends RecyclerView.Adapter<ProductCardViewHolder> {

   private List<ProductEntry> productList;
   private ImageRequester imageRequester;

   ProductCardRecyclerViewAdapter(List<ProductEntry> productList) {
       this.productList = productList;
       imageRequester = ImageRequester.getInstance();
   }

   @NonNull
   @Override
   public ProductCardViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
       View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.shr_product_card, parent, false);
       return new ProductCardViewHolder(layoutView);
   }

   @Override
   public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
       // TODO: Put ViewHolder binding code here in MDC-102
   }

   @Override
   public int getItemCount() {
       return productList.size();
   }
}

上記のアダプター クラスは、グリッドのコンテンツを管理します。それぞれのコンテンツで特定のコンテンツをどのように処理するかを決定するため、まもなく onBindViewHolder() のコードを記述します。

同じパッケージで ProductCardViewHolder もご覧ください。このクラスはカード レイアウトに影響するビューを保存するため、後で変更できます。

ProductCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import android.view.View;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       // TODO: Find and store views from itemView
   }
}

グリッドを設定するには、まず shr_product_grid_fragment.xml からプレースホルダ MaterialCardView を削除します。次に、カードのグリッドを表すコンポーネントを追加します。この場合、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 ステートメントの前に、RecyclerView 初期化コードを ProductGridFragment.java に追加します。

ProductGridFragment.java

@Override
public View onCreateView(
       @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
   ...
   setUpToolbar(view);

   // Set up the RecyclerView
   RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
   recyclerView.setHasFixedSize(true);
   recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
   ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
           ProductEntry.initProductEntryList(getResources()));
   recyclerView.setAdapter(adapter);
   int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
   int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
   recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

   return view;
}

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

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

ProductGridFragment.java

package com.google.codelabs.mdc.java.shrine;

import android.os.Bundle;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toolbar;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;


import com.google.codelabs.mdc.java.shrine.network.ProductEntry;

public class ProductGridFragment extends Fragment {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
   }

   @Override
   public View onCreateView(
           @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
       // Inflate the layout for this fragment with the ProductGrid theme
       View view = inflater.inflate(R.layout.shr_product_grid_fragment, container, false);

       // Set up the toolbar
       setUpToolbar(view);

       // Set up the RecyclerView
       RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
       recyclerView.setHasFixedSize(true);
       recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2, GridLayoutManager.VERTICAL, false));
       ProductCardRecyclerViewAdapter adapter = new ProductCardRecyclerViewAdapter(
               ProductEntry.initProductEntryList(getResources()));
       recyclerView.setAdapter(adapter);
       int largePadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing);
       int smallPadding = getResources().getDimensionPixelSize(R.dimen.shr_product_grid_spacing_small);
       recyclerView.addItemDecoration(new ProductGridItemDecoration(largePadding, smallPadding));

       return view;
   }

   private void setUpToolbar(View view) {
       Toolbar toolbar = view.findViewById(R.id.app_bar);
       AppCompatActivity activity = (AppCompatActivity) getActivity();
       if (activity != null) {
           activity.setSupportActionBar(toolbar);
       }
   }

   @Override
   public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) {
       menuInflater.inflate(R.menu.shr_toolbar_menu, menu);
       super.onCreateOptionsMenu(menu, menuInflater);
   }

}

ビルドして実行する。

カードが準備できましたまだ何も表示されないので、商品データを追加しましょう。

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

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

ProductCardViewHolder.java

package com.google.codelabs.mdc.java.shrine;

import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;

import com.android.volley.toolbox.NetworkImageView;

public class ProductCardViewHolder extends RecyclerView.ViewHolder {

   public NetworkImageView productImage;
   public TextView productTitle;
   public TextView productPrice;

   public ProductCardViewHolder(@NonNull View itemView) {
       super(itemView);
       productImage = itemView.findViewById(R.id.product_image);
       productTitle = itemView.findViewById(R.id.product_title);
       productPrice = itemView.findViewById(R.id.product_price);
   }
}

RecyclerView のアダプタで、ViewHolder,onBindViewHolder() メソッドを更新して、各ビューの情報を設定します。

ProductCardRecyclerViewAdapter.java

@Override
public void onBindViewHolder(@NonNull ProductCardViewHolder holder, int position) {
   if (productList != null && position < productList.size()) {
       ProductEntry product = productList.get(position);
       holder.productTitle.setText(product.title);
       holder.productPrice.setText(product.price);
       imageRequester.setImageFromUrl(holder.productImage, product.url);
   }
}

上記のコードは、ViewHolder を使用して、RecyclerView アダプタに各カードの処理方法を指定します。

ここでは、それぞれの ViewHolderTextView にテキストデータを設定し、ImageRequester を呼び出して URL から画像を取得しています。ImageRequester は、便宜上用意したクラスであり、Volley ライブラリを使用します(この Codelab の範囲外のトピックですが、自由にコードを探索できます)。

ビルドして実行します。

製品がアプリに表示されるようになりました。

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

次のステップ

トップ アプリバー、カード、テキスト フィールド、ボタンを使用して、MDC-Android ライブラリの 4 つのコア マテリアル デザイン コンポーネントを使用しました。MDC-Android Catalog の MDC Android のコンポーネントには、さらに多くのコンポーネントが含まれています。

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

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

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

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

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