より洗練されたユーザー エクスペリエンスを作成する

前の Codelab で学んだように、マテリアルは Google が作成したデザイン システムであり、ユーザー インターフェース設計のベスト プラクティスをサポートするガイドライン、コンポーネント、ツールで構成されています。この Codelab では、チップ計算アプリ(前の Codelabで作成)を更新して、次の最終スクリーンショットに示されている洗練されたユーザー エクスペリエンスを実現します。また、ユーザー エクスペリエンスができるだけスムーズなものになるように、いくつかの追加のシナリオでアプリをテストします。

5743ac5ee2493d7.png

前提条件

  • 一般的な UI ウィジェット(TextViewImageViewButtonEditTextRadioButtonRadioGroupSwitch など)に精通している
  • ConstraintLayout と、制約を設定して子ビューを配置する処理に精通している
  • XML レイアウトの変更に慣れている
  • ビットマップ画像とベクター型ドローアブルの違いを理解している
  • テーマにテーマ属性を設定できる
  • デバイスでダークテーマを有効にできる
  • アプリの build.gradle ファイルでプロジェクトの依存関係を変更した経験がある

学習内容

  • アプリでマテリアル デザイン コンポーネントを使用する方法
  • Image Asset Studio からマテリアル アイコンをインポートしてアプリで使用する方法
  • 新しいスタイルを作成し、適用する方法
  • 色以外のテーマ属性を設定する方法

作成するアプリの概要

  • 推奨される UI のベスト プラクティスに基づく洗練されたチップ計算アプリ

必要なもの

  • Android Studio がインストールされているパソコン
  • 前の Codelab で作成した Tip Time アプリのコード

前の Codelab では、Tip Time アプリを作成しました。このアプリは、チップをカスタマイズするオプションを含むチップ計算アプリです。現在、アプリの UI は以下のスクリーンショットのように表示されます。機能は問題ありませんが、プロトタイプのように見えます。フィールドが見やすく配置されていません。スタイルと間隔の一貫性、およびマテリアル デザイン コンポーネントの使用という観点から見ると、明らかに改善の余地があります。

6685eaafba30960a.png

マテリアル コンポーネントは、アプリにマテリアル スタイル設定を簡単に実装できる一般的な UI ウィジェットです。このドキュメントでは、マテリアル デザイン コンポーネントの使用方法とカスタマイズ方法について説明します。コンポーネントにはそれぞれ一般的なマテリアル デザイン ガイドラインがあり、Android で利用可能なコンポーネントについては Android プラットフォーム固有のガイダンスがあります。選択しているプラットフォームにコンポーネントが存在しない場合は、ラベル付きの図を参照して、コンポーネントを再作成するための十分な情報を得ることができます。

c4a4db857bb36c3f.png

マテリアル コンポーネントを使用すると、作成するアプリの動作とユーザーのデバイス上の他のアプリの動作の一貫性が向上します。つまり、あるアプリで習得した UI パターンを別のアプリでも使用できます。そのため、ユーザーは新しいアプリの使い方をより短時間で習得できます。可能な場合は、非マテリアル ウィジェットではなく、マテリアル コンポーネントを使用することをおすすめします。また、次のタスクで学習するように、マテリアル コンポーネントはより柔軟なカスタマイズが可能です。

マテリアル デザイン コンポーネント(MDC)ライブラリをプロジェクトの依存関係として含める必要があります。Android Studio 4.1 以降を使用している場合は、デフォルトで次の行がプロジェクトに存在するはずです。アプリの build.gradle ファイルで、この依存関係が最新バージョンのライブラリに含まれていることを確認します。詳しくは、マテリアルのサイトのスタートガイド ページをご覧ください。

app/build.gradle

dependencies {
    ...
    implementation 'com.google.android.material:material:<version>'
}

テキスト フィールド

現在、チップ計算アプリでは、レイアウトの上部に、サービス料金を表す EditText フィールドが表示されます。この EditText フィールドは機能に問題はありませんが、テキスト フィールドの外観と動作に関する最近のマテリアル デザイン ガイドラインに従っていません。

新しいコンポーネントを使用する際は、まずマテリアルのサイトでそのコンポーネントについて確認してください。テキスト フィールドに関するガイドによると、テキスト フィールドには次の 2 つのタイプがあります。

塗りつぶしテキスト フィールド

bea54a560820fe84.png

枠線付きテキスト フィールド

c37af7d70aad8aa6.png

上記のテキスト フィールドを作成するには、MDC ライブラリの TextInputEditText を包含する TextInputLayout を使用します。マテリアル テキスト フィールドは、次のように簡単にカスタマイズできます。

  • 入力テキストまたは常時表示されるラベルを表示する
  • テキスト フィールド内にアイコンを表示する
  • ヘルパーまたはエラー メッセージを表示する

この Codelab の最初のタスクでは、サービス料金の EditText を、TextInputLayoutTextInputEditText で構成されるマテリアル テキスト フィールドに置き換えます。

  1. Android Studio で Tip Time アプリを開いたまま、activity_main.xml レイアウト ファイルに移動します。このファイルにはチップ計算レイアウトの ConstraintLayout が含まれている必要があります。
  2. マテリアル テキスト フィールドに対応する XML のサンプルについては、Android のガイダンスに戻ってテキスト フィールドをご覧ください。次のようなスニペットを確認できます。
<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/textField"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="@string/label">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
    />

</com.google.android.material.textfield.TextInputLayout>
  1. このサンプルを確認した後、マテリアル テキスト フィールドを ConstraintLayout の最初の子として(EditText フィールドの前に)挿入します。EditText フィールドは、この後のステップで削除します。

Android Studio でこれを入力する場合は、オートコンプリートを使用して簡単に入力できます。または、ドキュメントのページからサンプル XML をコピーして、次のようにレイアウトに貼り付けることもできます。TextInputLayout に子ビュー TextInputEditText があることに注目してください。実際に変更された XML の行に注意を向けられるように、省略記号(...)を使用してスニペットの表示を簡潔にしています。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    ...>

    <com.google.android.material.textfield.TextInputLayout
        android:id="@+id/textField"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/label">

        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
        />

    </com.google.android.material.textfield.TextInputLayout>

    <EditText
        android:id="@+id/cost_of_service" ... />

    ...

TextInputLayout 要素に誤りがあることにお気づきでしょうか。このビューは、まだ親 ConstraintLayout 内で適切に制限されていません。また、文字列リソースが認識されていません。これらの誤りはこの後のステップで修正します。

1cf3f25cc047f291.png

  1. ConstraintLayout 内にテキスト フィールドを適切に配置するには、テキスト フィールドに縦方向と横方向の制約を追加します。まだ EditText を削除していないため、次の属性を EditText から切り取って貼り付け、TextInputLayout に配置します: 制約、リソース ID(cost_of_service)、レイアウトの幅(160dp)、レイアウトの高さ(wrap_content)、チップのテキスト(@string/cost_of_service)。
...

<com.google.android.material.textfield.TextInputLayout
   android:id="@+id/cost_of_service"
   android:layout_width="160dp"
   android:layout_height="wrap_content"
   android:hint="@string/cost_of_service"
   app:layout_constraintStart_toStartOf="parent"
   app:layout_constraintTop_toTopOf="parent">

   <com.google.android.material.textfield.TextInputEditText
       android:layout_width="match_parent"
       android:layout_height="wrap_content"/>

</com.google.android.material.textfield.TextInputLayout>

...

cost_of_service ID が EditText のリソース ID と同じであるというエラーが表示される場合がありますが、このエラーは今のところ無視してかまいません(EditText はこの後のステップで削除します)。

  1. 次に、TextInputEditText 要素に適切な属性がすべて設定されていることを確認します。EditText からの入力タイプを切り取って TextInputEditText. に貼り付け、TextInputEditText 要素のリソース ID を cost_of_service_edit_text. に変更します。
<com.google.android.material.textfield.TextInputLayout ... >

   <com.google.android.material.textfield.TextInputEditText
       android:id="@+id/cost_of_service_edit_text"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:inputType="numberDecimal" />

</com.google.android.material.textfield.TextInputLayout>

match_parent の幅と wrap_content の高さはそのままでかまいません。match_parent の幅を設定すると、TextInputEditText の幅はその親である TextInputLayout と同じ(160dp)になります。

  1. 以上で EditText からすべての関連情報をコピーしたので、次はレイアウトから EditText を削除します。
  2. レイアウトのデザインビューに、次のようなプレビューが表示されます。サービス料金フィールドがマテリアル テキスト フィールドらしく表示されています。

148df54f0deda630.png

  1. MainActivity.kt ファイルの calculateTip() メソッドに誤りがあるため、まだアプリを実行することはできません。以前の Codelab で、プロジェクトでビュー バインディングが有効になっていると、リソース ID 名に基づいてバインディング オブジェクト内にプロパティが作成されたことを思い出してください。サービス料金の取得元フィールドが XML レイアウトで変更されたため、それに応じて Kotlin コードを更新する必要があります。

リソース ID が cost_of_service_edit_textTextInputEditText 要素から、ユーザー入力を取得します。MainActivity 内で、binding.costOfServiceEditText を使用して、その中に格納されているテキスト文字列にアクセスします。calculateTip() メソッド残りの部分は同じままでかまいません。

private fun calculateTip() {
    // Get the decimal value from the cost of service text field
    val stringInTextField = binding.costOfServiceEditText.text.toString()
    val cost = stringInTextField.toDoubleOrNull()

    ...
}
  1. おつかれさまでした。アプリを実行して、前と同様に動作することを確認してください。入力すると、[Cost of Servive] ラベルが入力の上に表示されます。以前と同様、想定どおりにチップが計算されるはずです。

b4a27e58f63417b7.png

スイッチ

マテリアル デザイン ガイドラインには、スイッチに関するガイダンスもあります。スイッチとは、設定のオン / オフを切り替えられるウィジェットです。

  1. マテリアル スイッチについては、Android のガイダンスをご確認ください。スイッチ用のマテリアル スタイル設定を提供する SwitchMaterial ウィジェット(MDC ライブラリにあります)について学習できます。引き続きガイドをスクロールすると、サンプル XML が表示されます。
  2. SwitchMaterial を使用するには、レイアウト内で SwitchMaterial を明示的に指定し、完全修飾パス名を使用する必要があります。

activity_main.xml レイアウト内で、XML タグを Switch から com.google.android.material.switchmaterial.SwitchMaterial. に変更します。

...

<com.google.android.material.switchmaterial.SwitchMaterial
    android:id="@+id/round_up_switch"
    android:layout_width="0dp"
    android:layout_height="wrap_content" ... />

...
  1. アプリを実行して、前と同様に動作することを確認します。アプリに目に見える変化はありません。ただし、Android プラットフォームの Switch の代わりに MDC ライブラリの SwitchMaterial を使用するメリットは、SwitchMaterial 用のライブラリの実装が更新されたとき(例: マテリアル デザイン ガイドラインが変更されたとき)に、アプリを一切変更せずに、更新されたウィジェットを無料で利用できることです。これは、アプリを将来も有効に使い続けるために役立ちます。

ここまでは、すぐに使えるマテリアル デザイン コンポーネントの使用が UI にもたらすメリットと、アプリをマテリアル ガイドラインに近づける方法に関する 2 つの例を見てきました。Android で提供されるその他のマテリアル デザイン コンポーネントについては、こちらのサイトでいつでも確認できます。

アイコンとは、目的の機能を視覚的に伝達することで、ユーザーがユーザー インターフェースを理解することを助けるシンボルです。多くの場合、アイコンはユーザーがよく知っていると思われる現実の物体から着想を得ています。ほとんどのアイコンのデザインは、ユーザーが即座に理解できる最小限のレベルまで簡略化されています。たとえば、現実の鉛筆は字を書くために使用されるので、通常、鉛筆のアイコンはアイテムの作成、追加、編集を表します。

写真撮影: Angelina Litvin(出典: Unsplash

フロッピー ディスク アイコンのように、かつて実際にあった物体に関連するアイコンもあります。このアイコンは、ファイルやデータベース レコードの保存を表すためによく使われます。しかし、フロッピー ディスクは 1970 年代は一般的でしたが、2000 年以降はほとんど使われなくなりました。それにもかかわらずこのアイコンが今でも使われているということは、強力な視覚的デザインが物質的形態としての寿命を越えていかに長く生き続けるかを物語っています。

写真撮影: Vincent Botta(出典: Unsplash

アプリ内のアイコンの表現

アプリ内のアイコンでは、画面密度ごとに異なるバージョンのビットマップ画像を使用する代わりに、ベクター型ドローアブルを使用することをおすすめします。ベクター型ドローアブルは、画像を構成する実際のピクセルを保存するのではなく、画像の作成方法を指示する XML ファイルとして表現されます。ベクター型ドローアブルは、画質の低下とファイルサイズの増大を招くことなく、拡大または縮小できます。

提供されるアイコン

マテリアル デザインでは、多くのニーズに対応した多数のアイコンが一般的なカテゴリ別に用意されています。アイコンの一覧をご覧ください

76e9b6c4ec0cbbe6.png

また、アイコンは 5 つのテーマ(塗りつぶし、枠線付き、角丸、ツートン、鋭角)のいずれかを使用して描画できます。色を使用して色合いを調整することもできます。

塗りつぶし

枠線付き

角丸

ツートン

鋭角

アイコンを追加する

このタスクでは、次の 3 つのベクター型ドローアブル アイコンをアプリに追加します。

  1. サービス料金テキスト フィールドの横のアイコン
  2. サービスに関する質問の横のアイコン
  3. チップの端数切り上げプロンプトの横のアイコン

アプリの最終バージョンのスクリーンショットは以下のとおりです。アイコンを追加した後、アイコンの配置に合わせてレイアウトを調整します。フィールドと計算ボタンが右にずらされ、アイコンが追加されていることに注目してください。

8c4225390dd1fb20.png

ベクター型ドローアブル アセットを追加する

これらのアイコンは、Android Studio の Asset Studio から直接、ベクター型ドローアブルとして作成できます。

  1. アプリ ウィンドウの左側にある [Resource Manager] タブを開きます。
  2. プラス(+)アイコンをクリックして [Vector Asset] を選択します。

6a692157a2ada3f6.png

  1. [Asset Type] で [Clip Art] ラジオボタンがオンになっていることを確認します。

698ab1c8dc2d1714.png

  1. [Clip Art] の横のボタンをクリックして、別のクリップアート画像を選択します。表示されたプロンプトで、ウィンドウに「call made」と入力します。この矢印アイコンは、チップの端数切り上げオプションに使用します。このアイコンを選択して [OK] をクリックします。

50b0008ed6ab8d6d.png

  1. アイコンの名前を ic_round_up に変更します(アイコン ファイルの名前には、接頭辞 ic_ を使用することをおすすめします)。[**Size*] は 24 dp x 24 dp、[**Color**] は黒(000000)のままでかまいません。
  2. [Next] をクリックします。
  3. デフォルトのディレクトリの場所を受け入れて [Finish] をクリックします。

9f522a73be34ecf6.png

  1. 他の 2 つのアイコンについて、ステップ 2~7 を繰り返します。
  • サービスに関する質問のアイコン:「room service」アイコンを検索し、ic_service として保存します。
  • サービス料金のアイコン:「store」アイコンを検索し、ic_store として保存します。
  1. 完了すると、Resource Manager が以下のスクリーンショットのように表示されます。また、これら 3 つのベクター型ドローアブル(ic_round_upic_serviceic_store)が res/drawable フォルダ内に表示されます。

3c895747fbfa3793.png

古い Android バージョンをサポートする

たった今ベクター型ドローアブルをアプリに追加しましたが、Android プラットフォームでのベクター型ドローアブルのサポートは、Android 5.0(API レベル 21)未満では追加されていないことに注意する必要があります。

プロジェクトを設定した方法に基づき、Tip Time アプリの最小 SDK バージョンは API 19 です。つまり、このアプリを実行できるのは、Android プラットフォーム バージョン 19 以上を搭載した Android デバイスです。

それより古いバージョンの Android でアプリを動作させる(いわゆる下位互換性を維持する)には、アプリの build.gradle ファイルに vectorDrawables 要素を追加します。そうすれば、API 21 未満のバージョンのプラットフォームでベクター型ドローアブルを使用できます。プロジェクトのビルド時に PNG に変換する必要はありません。詳しくは、こちらをご覧ください

app/build.gradle

android {
  defaultConfig {
    ...
    vectorDrawables.useSupportLibrary = true
   }
   ...
}

プロジェクトが適切に構成されていれば、これでアイコンをレイアウトに追加できるようになります。

アイコンと位置要素を挿入する

アプリ内にアイコンを表示するには、ImageViews を使用します。最終的な UI は次のように表示されます。

5d970eb04c642544.png

  1. activity_main.xml レイアウトを開きます。
  2. まず、サービス料金テキスト フィールドの横にストアのアイコンを配置します。ConstraintLayout の最初の子として、TextInputLayout の前に新しい ImageView を挿入します。
<androidx.constraintlayout.widget.ConstraintLayout
   ...>

   <ImageView
       android:layout_width=""
       android:layout_height=""

   <com.google.android.material.textfield.TextInputLayout
       android:id="@+id/cost_of_service"
       ...
  1. ic_store アイコンを保持する ImageView に適切な属性を設定します。ID を icon_cost_of_service に設定します。app:srcCompat 属性をドローアブル リソース @drawable/ic_store に設定します。これにより、XML の該当行の横にアイコンのプレビューが表示されます。この画像は装飾目的でのみ使用するので、android:importantForAccessibility="no" も設定します。
<ImageView
    android:id="@+id/icon_cost_of_service"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:importantForAccessibility="no"
    app:srcCompat="@drawable/ic_store" />

ビューがまだ制限されていないため、ImageView にエラーがあるはずです。これは後で修正します。

  1. 2 つのステップで icon_cost_of_service の位置を調整します。最初に(このステップで)ImageView に制約を追加し、次に(ステップ 5 で)その横にある TextInputLayout の制約を更新します。次の図は、制約の設定方法を示しています。

e23287bdeca07a1e.png

ImageView で、その始端を親ビューの始端に制限します(app:layout_constraintStart_toStartOf="parent")。

アイコンは横にあるテキスト フィールドに対して縦方向の中央に表示されるため、この ImageView の最上部(layout_constraintTop_toTopOf)をテキスト フィールドの最上部に制限します。この ImageView の最下部(layout_constraintBottom_toBottomOf)をテキスト フィールドの最下部に制限します。テキスト フィールドを参照するには、リソース ID @id/cost_of_service を使用します。デフォルトの動作では、2 つの制約が同じディメンション(最上部と最下部の制約など)でウィジェットに適用される場合、制約は均等に適用されます。その結果、アイコンはサービス料金フィールドに対して縦方向の中央に配置されます。

<ImageView
    android:id="@+id/icon_cost_of_service"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:importantForAccessibility="no"
    app:srcCompat="@drawable/ic_store"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="@id/cost_of_service"
    app:layout_constraintBottom_toBottomOf="@id/cost_of_service" />

デザインビューでは、アイコンとテキスト フィールドが依然として重なり合っています。これは次のステップで修正します。

  1. アイコンを追加する前、テキスト フィールドは親の開始位置に配置されていました。これを右にずらす必要があります。icon_cost_of_service に関する cost_of_service テキスト フィールドの制約を更新します。

40c0c8f04f53a87d.png

TextInputLayout の始端を ImageView@id/icon_cost_of_service)の終端に制限する必要があります。2 つのビューの間隔を広げるには、TextInputLayout に開始余白 16dp を追加します。

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/cost_of_service"
    ...
    android:layout_marginStart="16dp"
    app:layout_constraintStart_toEndOf="@id/icon_cost_of_service">

    <com.google.android.material.textfield.TextInputEditText ... />

</com.google.android.material.textfield.TextInputLayout>

以上の変更が完了したら、アイコンをテキスト フィールドの真横に配置する必要があります。

6ca04c3c964d5acc.png

  1. 次に、[How was the service?] の TextView の横に、サービスを表すベルのアイコンを挿入します。ImageViewConstraintLayout 内の任意の場所で宣言できますが、XML レイアウトで新しい ImageViewTextInputLayout の後、service_question TextView の前に挿入すると、XML レイアウトが読みやすくなります。

新しい ImageView には、@+id/icon_service_question のリソース ID を割り当てます。ImageView とサービスに関する質問の TextView に適切な制約を設定します。

4487340b399e8105.png

また、service_question TextView16dp の上余白を追加し、サービスに関する質問とその上にあるサービス料金テキスト フィールドの間にある縦の間隔を広げます。

...

   <ImageView
        android:id="@+id/icon_service_question"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:importantForAccessibility="no"
        app:srcCompat="@drawable/ic_service"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/service_question"
        app:layout_constraintBottom_toBottomOf="@id/service_question" />

    <TextView
        android:id="@+id/service_question"
        ...
        android:layout_marginTop="16dp"
        app:layout_constraintStart_toStartOf="@id/cost_of_service"
        app:layout_constraintTop_toBottomOf="@id/cost_of_service"/>

...
  1. この時点で、デザインビューは次のように表示されます。サービス料金フィールドとサービスに関する質問(およびそれぞれのアイコン)の配置は改善されましたが、今度はラジオボタンの位置がずれています。上にあるコンテンツと縦の位置が揃っていません。

cdfd16c1851c88eb.png

  1. サービスに関する質問の下にあるラジオボタンを右にずらして、位置を調整します。つまり、RadioGroup 制約を更新します。RadioGroup の始端を service_question TextView の始端に制限します。RadioGroup の残りの属性はすべて同じままでかまいません。

58a62fae3d676fe4.png

...

<RadioGroup
    android:id="@+id/tip_options"
    ...
    app:layout_constraintStart_toStartOf="@id/service_question">

...
  1. 次に、[Round up tip?] スイッチの横にあるレイアウトに ic_round_up アイコンを追加します。これはご自分でトライしてください。行き詰ったときは、下記の XML が参考になります。新しい ImageView には、リソース ID icon_round_up を割り当てることができます。
  2. レイアウト XML で、RadioGroup の後、SwitchMaterial ウィジェットの前に、新しい ImageView を挿入します。
  3. ImageView にリソース ID icon_round_up を割り当てて、srcCompat をアイコン @drawable/ic_round_up のドローアブルに設定します。ImageView の開始位置を親の開始位置に制限し、また、SwitchMaterial を基準としてアイコンを縦方向の中央に配置します。
  4. アイコンの横に配置されるように SwitchMaterial を更新し、16dp の開始余白を設定します。結果として生成される XML は、icon_round_up および round_up_switch のようになります。
...

   <ImageView
        android:id="@+id/icon_round_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:importantForAccessibility="no"
        app:srcCompat="@drawable/ic_round_up"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@id/round_up_switch"
        app:layout_constraintBottom_toBottomOf="@id/round_up_switch" />

    <com.google.android.material.switchmaterial.SwitchMaterial
        android:id="@+id/round_up_switch"
        ...
        android:layout_marginStart="16dp"
        app:layout_constraintStart_toEndOf="@id/icon_round_up" />

...
  1. デザイン ビューは次のようになります。3 つのアイコンがすべて正しく配置されています。

f4b0e8d61d91986b.png

  1. これをアプリの最終スクリーンショットと比べると、計算ボタンも、サービス料金フィールド、サービスに関する質問、ラジオボタンのオプション、チップの端数切り上げプロンプトと縦に揃うようにずらされていることがわかります。そのような配置を実現するには、計算ボタンの開始位置を round_up_switch の開始位置に制限します。また、計算ボタンとその上のスイッチの間に、8dp の縦方向の余白を追加します。

60d5a43819c2367d.png

...

<Button
   android:id="@+id/calculate_button"
   ...
   android:layout_marginTop="8dp"
   app:layout_constraintStart_toStartOf="@id/round_up_switch" />

...
  1. 最後に重要な作業として、TextView8dp の上余白を追加し、tip_result の位置を調整します。

beb333a518b51323.png

...

<TextView
   android:id="@+id/tip_result"
   ...
   android:layout_marginTop="8dp" />

...
  1. たくさんのステップがありましたが、順を追って実施すれば大きな成果が得られます。レイアウト内に要素を正しく配置するには細部に十分な注意を払う必要がありますが、その結果として外観が大幅に改善されます。アプリを実行すると、以下のスクリーンショットのようになります。要素を縦に揃えて要素間の間隔を広げたことで、要素が密集していないすっきりしたレイアウトになりました。

1f2ef2c0c9a9bdc7.png

作業はこれで終わりではありません。サービスに関する質問とチップ金額のフォントサイズと色が、ラジオボタンとスイッチのテキストと異なることにお気づきでしょうか。次のタスクでは、スタイルとテーマを使用して、この点についても一貫性を実現します。

スタイルとは、ウィジェットの単一のタイプに対応するビュー属性値のコレクションです。たとえば、TextView スタイルで、フォントの色、フォントサイズ、背景色などを指定できます。これらの属性をスタイルに抽出すると、レイアウト内の複数のビューにスタイルを適用し、一元的に管理することが容易になります。

このタスクでは、最初にテキストビュー、ラジオボタン、スイッチ ウィジェットのスタイルを作成します。

スタイルを作成する

  1. res > values ディレクトリに styles.xml という名前のファイルがない場合は、新たに作成します。作成するには、values ディレクトリを右クリックして、[New] > [Values Resource File] を選択します。styles.xml という名前を付けます。新しいファイルには次の行が含まれています。
<?xml version="1.0" encoding="utf-8"?>
<resources>
</resources>
  1. 新しい TextView スタイルを作成して、アプリ全体でテキストの表示に一貫性を持たせます。styles.xml で一度スタイルを定義すると、レイアウト内のすべての TextViews にそれを適用できます。スタイルは、ゼロから定義することも、MDC ライブラリの既存の TextView スタイルから拡張することもできます。

通常、コンポーネントのスタイルを設定する際は、使用するウィジェット タイプの親スタイルから拡張する必要があります。これは 2 つの理由で重要です。第 1 に、すべての重要なデフォルト値が確実にコンポーネントに設定されます。第 2 に、親スタイルに対する今後のすべての変更が引き続きスタイルに継承されます。

スタイルには任意の名前を付けることができますが、推奨される命名規則があります。親マテリアル スタイルから継承する場合は、MaterialComponents をアプリの名前(TipTime)に置き換えて、類似したスタイル名を付けます。そうすると、変更が固有の名前空間に移動されるため、今後マテリアル コンポーネントに新しいスタイルが導入されたときに、競合する可能性を回避できます。例:

スタイル名: Widget.TipTime.TextView 親スタイルからの継承: Widget.MaterialComponents.TextView

styles.xml ファイルで、これを resources の開始タグと終了タグの間に追加します。

<style name="Widget.TipTime.TextView" parent="Widget.MaterialComponents.TextView">
</style>
  1. TextView スタイルを設定して、属性 android:minHeight,android:gravity, および android:textAppearance. をオーバーライドします。

android:minHeight は、TextView の高さの最小値を 48 dp に設定します。すべての行の高さの最小値は、マテリアル デザイン ガイドラインに従って 48 dp にする必要があります。

android:gravity 属性を設定すると、TextView のテキストを縦方向の中央に配置できます(以下のスクリーンショットをご覧ください)。gravity は、ビュー内のコンテンツの位置を制御します。実際のテキスト コンテンツの高さは 48 dp を超えないので、値 center_vertical により TextView 内のテキストは縦方向の中央に配置されます(横方向の位置は変更されません)。gravity には、これ以外に centercenter_horizontaltopbottom などの値を指定できます。よろしければ、他の gravity の値を試して、テキストに及ぼす効果を確認してみてください。

bd89f5a76d67ada6.png

テキスト表示属性の値を ?attr/textAppearanceBody1 に設定します。TextAppearance は、テキストサイズ、フォント、およびテキストのその他プロパティに関する事前作成済みのスタイルのセットです。マテリアルが提供するその他の可能なテキスト表示については、こちらの型スケールのリストをご覧ください。

<style name="Widget.TipTime.TextView" parent="Widget.MaterialComponents.TextView">
    <item name="android:minHeight">48dp</item>
    <item name="android:gravity">center_vertical</item>
    <item name="android:textAppearance">?attr/textAppearanceBody1</item>
</style>
  1. activity_main.xml の各 TextView にスタイル属性を追加することにより、Widget.TipTime.TextView スタイルを service_question TextView に適用します。
<TextView
    android:id="@+id/service_question"
    style="@style/Widget.TipTime.TextView"
    ... />

スタイルを追加する前、TextView は、小さいフォントサイズとグレーのフォントカラーで次のように表示されていました。

5cd99583da77efba.png

スタイルを追加した後、TextView は次のようになります。これで、この TextView とレイアウトの他の部分との一貫性が向上しました。

296a89a6015d9e15.png

  1. 同じ Widget.TipTime.TextView スタイルを tip_result TextView に適用します。
<TextView
    android:id="@+id/tip_result"
    style="@style/Widget.TipTime.TextView"
    ... />

c45860bda6761be7.png

  1. 同じテキスト スタイルをスイッチのテキストラベルに適用する必要があります。ただし、TextView スタイルを SwitchMaterial ウィジェットに設定することはできません。TextView スタイルは TextViews にのみ適用できます。したがって、スイッチ用の新しいスタイルを作成します。属性は、minHeightgravitytextAppearance については同じです。異なるのはスタイル名と親です。それらは MDC ライブラリの Switch スタイルから継承するからです。この場合も、スタイルの名前に、親スタイルの名前を反映させる必要があります。

スタイル名: Widget.TipTime.CompoundButton.Switch 親スタイルからの継承: Widget.MaterialComponents.CompoundButton.Switch

<style name="Widget.TipTime.CompoundButton.Switch" parent="Widget.MaterialComponents.CompoundButton.Switch">
   <item name="android:minHeight">48dp</item>
   <item name="android:gravity">center_vertical</item>
   <item name="android:textAppearance">?attr/textAppearanceBody1</item>
</style>

このスタイルのスイッチに固有の追加属性を指定することもできますが、このアプリではその必要はありません。

  1. テキストの表示に一貫性を持たせる必要がある最後の箇所は、ラジオボタンのテキストです。TextView スタイルまたは Switch スタイルを RadioButton ウィジェットに適用することはできません。代わりに、ラジオボタン用の新しいスタイルを作成する必要があります。これは、MDC ライブラリの RadioButton スタイルから拡張できます。

このスタイルを作成する際に、ラジオボタン テキストと円形のシンボルの間にパディングを追加します。paddingStart は、まだ使用したことがない新しい属性です。パディングとは、ビューのコンテンツとビューの境界の間のスペースの量です。paddingStart 属性は、コンポーネントの開始位置にのみパディングを設定します。ラジオボタンの paddingStart を 0 dp にした場合と 8 dp にした場合の違いを次に示します。

e1cef41d95740600.png

25f75f5c36085e76.png

<style name="Widget.TipTime.CompoundButton.RadioButton"
parent="Widget.MaterialComponents.CompoundButton.RadioButton">
   <item name="android:paddingStart">8dp</item>
   <item name="android:textAppearance">?attr/textAppearanceBody1</item>
</style>
  1. (省略可)dimens.xml ファイルを作成すると、頻繁に使用する値の管理が容易になります。このファイルは、前述の styles.xml ファイルと同じ方法で作成できます。values ディレクトリを選択し、右クリックして [New] > [Values Resource File] を選択します。

これまでに、この小さなアプリで高さの最小値の設定を 2 回繰り返しました。この程度であれば簡単に管理できますが、4 個、6 個、10 個、またはそれ以上のコンポーネントがこの値を共有するとなると、たちまち管理が困難になります。それらすべてを個別に変更する作業は退屈で、間違いが発生しやすくなります。res > values ディレクトリに dimens.xml という名前の便利なリソース ファイルを作成し、そのファイルで共通のディメンションを保持できます。共通の値を名前付きディメンションとして標準化することにより、アプリの管理が容易になります。ただし、TipTime は小さなアプリなので、この省略可能なステップ以外ではこのファイルを使用しません。デザインチームと協力して作業する本番環境で複雑なアプリを作成する場合は、dimens.xml を使用すると、共通のディメンションの値を頻繁に変更することが容易になります。

dimens.xml

<resources>
   <dimen name="min_text_height">48dp</dimen>
</resources>

48dp を直接設定する代わりに、@dimen/min_text_height を使用するように styles.xml ファイルを更新します。

...
<style name="Widget.TipTime.TextView" parent="Widget.MaterialComponents.TextView">
    <item name="android:minHeight">@dimen/min_text_height</item>
    <item name="android:gravity">center_vertical</item>
    <item name="android:textAppearance">?attr/textAppearanceBody1</item>
</style>
...

スタイルをテーマに追加する

お気づきのとおり、新しい RadioButton および Switch スタイルをそれぞれのウィジェットにまだ適用していません。これは、テーマ属性を使用してアプリテーマに radioButtonStyleswitchStyle を設定するためです。テーマについてもう一度おさらいしましょう。

テーマとは、スタイルやレイアウトなどで後から参照できる名前付きリソース(テーマ属性と呼ばれます)のコレクションです。テーマは、個別の View. だけでなく、アプリ全体、アクティビティ、ビュー階層に対して指定できます。以前は colorPrimarycolorSecondary のようなテーマ属性を設定することにより、themes.xml でアプリテーマを変更していました。そして、テーマ属性はアプリとアプリのコンポーネント全体で使用されていました。

radioButtonStyleswitchStyle も設定可能なテーマ属性です。これらのテーマ属性に対して指定するスタイル リソースは、そのテーマが適用されるビュー階層内のすべてのラジオボタンとすべてのスイッチに適用されます。

指定されたスタイル リソースがアプリ内のすべてのテキスト入力フィールドに適用される、textInputStyle 用のテーマ属性もあります。TextInputLayout を(マテリアル デザイン ガイドラインで示されているとおり)枠線付きテキスト フィールドのように表示するには、MDC ライブラリで Widget.MaterialComponents.TextInputLayout.OutlinedBox として定義されている OutlinedBox スタイルを利用できます。ここでは、このスタイルを使用します。

b00a91da56e6f6e2.png

  1. テーマが目的のスタイルを参照するように、themes.xml ファイルを変更します。テーマ属性を設定する方法は、前の Codelab で colorPrimary および colorSecondary テーマ属性を宣言した方法と同じです。ただし、今回設定するテーマ属性は、textInputStyleradioButtonStyleswitchStyle です。前に RadioButton および Switch 用に作成したスタイルとともに、マテリアルの OutlinedBox テキスト フィールド用のスタイルを使用します。

次の行をコピーして、res/values/themes.xml のアプリテーマのスタイルタグに貼り付けます。

<item name="textInputStyle">@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox</item>
<item name="radioButtonStyle">@style/Widget.TipTime.CompoundButton.RadioButton</item>
<item name="switchStyle">@style/Widget.TipTime.CompoundButton.Switch</item>
  1. res/values/themes.xml ファイルは次のようになります。お望みであれば、XML にコメントを追加できます(コメントは <!---> で示します)。
<resources xmlns:tools="http://schemas.android.com/tools">

    <!-- Base application theme. -->
    <style name="Theme.TipTime" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        ...
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Text input fields -->
        <item name="textInputStyle">@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox</item>
        <!-- Radio buttons -->
        <item name="radioButtonStyle">@style/Widget.TipTime.CompoundButton.RadioButton</item>
        <!-- Switches -->
        <item name="switchStyle">@style/Widget.TipTime.CompoundButton.Switch</item>
    </style>

</resources>
  1. themes.xml(night)のダークテーマにも必ず同じ変更を加えてください。res/values-night/themes.xml ファイルは次のようになります。
<resources xmlns:tools="http://schemas.android.com/tools">

    <!-- Application theme for dark theme. -->
    <style name="Theme.TipTime" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        ...
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Text input fields -->
        <item name="textInputStyle">@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox</item>
        <!-- For radio buttons -->
        <item name="radioButtonStyle">@style/Widget.TipTime.CompoundButton.RadioButton</item>
        <!-- For switches -->
        <item name="switchStyle">@style/Widget.TipTime.CompoundButton.Switch</item>
    </style>

</resources>
  1. アプリを実行して、変更を確認します。OutlinedBox スタイルによってテキスト フィールドの外観が改善され、すべてのテキストの表示に一貫性がもたらされました。

31ac15991713b031.png 3e861407146c9ed4.png

アプリが完成に近づくにつれて、想定しているワークフローだけでなく、それ以外のユーザー シナリオでもアプリをテストする必要があります。わずかなコード変更で、ユーザー エクスペリエンスが大幅に改善されることがあります。

デバイスを回転させる

  1. デバイスを回転させて横表示にします。まず、[自動回転] 設定を有効にします(この設定は、デバイスの [クイック設定] か、[設定] > [ディスプレイ] > [詳細設定] > [画面の自動回転] オプションで行います)。

f2edb1ae9926d5f1.png

エミュレータでは、エミュレータ オプション(デバイスのすぐ隣の右上にあります)を使用して、画面を左右に回転させることができます。

da8aee11166adf41.png

  1. ご覧のとおり、[Calculate] ボタンなど、UI コンポーネントの一部の表示が切れています。これでは明らかにアプリを使用できません。

d73499f9c9d2b330.png

  1. この不具合を解決するには、ConstraintLayout を囲む ScrollView を追加します。XML は次のようになります。
<ScrollView
   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_height="match_parent"
   android:layout_width="match_parent">

   <androidx.constraintlayout.widget.ConstraintLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:padding="16dp"
       tools:context=".MainActivity">

       ...
   </ConstraintLayout>

</ScrollView>
  1. もう一度アプリを実行してテストします。デバイスを回転させて横表示にした場合、UI をスクロールすると計算ボタンが使用可能になり、チップの計算結果が表示されます。この修正は、横表示だけでなく、サイズが異なる他の Android デバイスでも有用です。これで、デバイスの画面サイズにかかわらず、ユーザーはレイアウトをスクロールできるようになります。

Enter キーでキーボードを非表示にする

サービス料金を入力した後もキーボードが表示されたままになることにお気づきでしょうか。計算ボタンを使用しやすくするために、毎回キーボードを手動で非表示にするのはいささか面倒です。代わりに、Enter キーが押されたらキーボードが自動的に非表示になるようにしましょう。

e2c3a3dbc40218a2.png

テキスト フィールドでは、特定のキーがタップされたときにイベントに応答するキーリスナーを定義できます。キーボードのすべての可能な入力オプションには、Enter キーを含むキーコードが関連付けられています。画面キーボードは、物理キーボードに対してソフト キーボードと呼ばれることもあります。

1c95d7406d3847fe.png

このタスクでは、テキスト フィールドにキーリスナーを設定して、Enter キーが押されたときにリッスンするようにします。このイベントが検出されたら、キーボードを非表示にします。

  1. 下記のヘルパー メソッドをコピーして MainActivity クラスに貼り付けます。MainActivity クラスの右中かっこの直前に挿入できます。handleKeyEvent() は、keyCode 入力パラメータが KeyEvent.KEYCODE_ENTER と等しい場合に画面キーボードを非表示にする非公開のヘルパー関数です。InputMethodManager は、ソフト キーボードの表示と非表示を制御し、表示されるソフト キーボードをユーザーが選択できるようにします。このメソッドは、キーイベントが処理された場合は true を返し、処理されなかった場合は false を返します。

MainActivity.kt

private fun handleKeyEvent(view: View, keyCode: Int): Boolean {
   if (keyCode == KeyEvent.KEYCODE_ENTER) {
       // Hide the keyboard
       val inputMethodManager =
           getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
       inputMethodManager.hideSoftInputFromWindow(view.windowToken, 0)
       return true
   }
   return false
}
  1. 次に、キーリスナーを TextInputEditText ウィジェットにアタッチします。バインディング オブジェクトを介して、binding.costOfServiceEditText. として TextInputEditText ウィジェットにアクセスできることを思い出してください。

costOfServiceEditTextsetOnKeyListener() メソッドを呼び出し、OnKeyListener を渡します。これは、binding.calculateButton.setOnClickListener { calculateTip() }. を使用して、アプリの計算ボタンにクリック リスナーを設定する方法と似ています。

ビューにキーリスナーを設定するコードはやや複雑ですが、キーの押下が発生したときにトリガーされる onKey() メソッドを OnKeyListener に設定するのが一般的な方法です。onKey() メソッドは 3 つの入力引数を受け取ります。それは、ビュー、押されたキーを表すコード、キーイベント(ここでは使用しないので、"_" を指定します)です。onKey() メソッドが呼び出されたら、handleKeyEvent() メソッドを呼び出して、ビューとキーコードの引数を渡す必要があります。これを記述する構文は、view, keyCode, _ -> handleKeyEvent(view, keyCode). です。これは実際にはラムダ式と呼ばれますが、ラムダの詳細については今後の学習ユニットで詳しく説明します。

アクティビティの onCreate() メソッド内のテキスト フィールドにキーリスナーを設定するコードを追加します。これは、レイアウトが作成された直後、ユーザーがアクティビティの操作を開始する前に、キーリスナーをアタッチする必要があるからです。

MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
   ...

   setContentView(binding.root)

   binding.calculateButton.setOnClickListener { calculateTip() }

   binding.costOfServiceEditText.setOnKeyListener { view, keyCode, _ -> handleKeyEvent(view, keyCode)
   }
}
  1. 新たに加えた変更が機能するかどうかをテストします。アプリを実行して、サービス料金を入力します。キーボードの Enter キーを押すと、ソフト キーボードが非表示になるはずです。

TalkBack を有効にしてアプリをテストする

このコースで学習してきたとおり、できるだけ多くのユーザーが利用できるアプリを作成する必要があります。一部のユーザーは、TalkBack を使用してアプリを操作する場合があります。TalkBack は、Android デバイスに組み込まれている Google スクリーン リーダーです。TalkBack から音声フィードバックが出力されるので、画面を見ずにデバイスを使用できます。

TalkBack を有効にして、ユーザーがこのアプリでチップの計算を完了できるかどうかを確認しましょう。

  1. デバイスで TalkBack を有効にするには、こちらの手順を実施します。
  2. Tip Time アプリに戻ります。
  3. こちらの手順に沿って、TalkBack でアプリを探します。右にスワイプして画面要素間を順番に移動し、左にスワイプして逆に移動します。選択するには、任意の場所をダブルタップします。スワイプ操作でアプリのすべての要素にアクセスできることを確認します。
  4. TalkBack ユーザーが画面上の各アイテムにナビゲートできることを確認した後、サービス料金を入力し、チップ オプションを変更して、チップを計算します。そうすると、チップ金額が読み上げられるはずです。アイコンは importantForAccessibility="no" としてマークしたため、アイコンの音声フィードバックは出力されないことにご注意ください。

アプリのユーザー補助機能を強化する方法について詳しくは、こちらの原則をご確認ください。

(省略可)ベクター型ドローアブルの色合いを調整する

この省略可能なタスクでは、テーマのメインカラーに基づいてアイコンの色合いを調整し、ライトテーマとダークテーマでアイコンの外観が変化するようにします(下記を参照)。この変更を行うと、アイコンとアプリテーマの調和が増し、UI がよりいっそう改善されます。

77092f702beb1cfb.png 80a390087905eb29.png

前述のように、ビットマップ画像と比較した場合の VectorDrawables の利点のひとつは、拡大縮小と色合い調整の機能です。ベルのアイコンを表す XML を下記に示します。特に注目すべきは、android:tintandroid:fillColor の 2 つの色属性です。

ic_service.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
   android:width="24dp"
   android:height="24dp"
   android:viewportWidth="24"
   android:viewportHeight="24"
   android:tint="?attr/colorControlNormal">
 <path
     android:fillColor="@android:color/white"
     android:pathData="M2,17h20v2L2,19zM13.84,7.79c0.1,-0.24 0.16,-0.51 0.16,-0.79 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2c0,0.28 0.06,0.55 0.16,0.79C6.25,8.6 3.27,11.93 3,16h18c-0.27,-4.07 -3.25,-7.4 -7.16,-8.21z"/>
</vector>

bdddc76d0ca06573.png

色合いが存在する場合、それによってドローアブルの fillColor ディレクティブがすべてオーバーライドされます。この場合は、白い色が colorControlNormal テーマ属性でオーバーライドされます。colorControlNormal は、ウィジェットの「標準」(選択されていない非アクティブの状態)の色です。現在、それはグレーです。

アプリの外観を改善する方法のひとつとして、アプリテーマのメインカラーに基づいてドローアブルの色合いを調整できます。アイコンは、ライトテーマでは @color/green として表示されますが、ダークテーマでは @color/green_light(これは ?attr/colorPrimary です)として表示されます。アプリテーマのメインカラーに基づいてドローアブルの色合いを調整すると、レイアウト内の要素の外観が統一され、調和が増します。また、ライトテーマとダークテーマ用に重複するアイコンのセットを保持せずに済みます。ベクター型ドローアブルのセットを 1 つだけ保持すれば、colorPrimary テーマ属性に基づいて色合いが変更されます。

  1. ic_service.xmlandroid:tint 属性の値を変更します。
android:tint="?attr/colorPrimary"

Android Studio では、このアイコンに適切な色合いが設定されています。

148a05c44b515c25.png

colorPrimary テーマ属性が指す値は、ライトテーマかダークテーマかによって異なります。

  1. 他のベクター型ドローアブルで色合いを変更するには、同じ手順を繰り返します。

ic_store.xml

<vector ...
   android:tint="?attr/colorPrimary">
   ...
</vector>

ic_round_up.xml

<vector ...
   android:tint="?attr/colorPrimary">
   ...
</vector>
  1. アプリを実行し、ライトテーマとダークテーマでアイコンの外観が異なることを確認します。
  2. 最終クリーンアップとして、アプリ内のすべての XML ファイルと Kotlin コードファイルを再フォーマットする手順を忘れずに実施してください。

おつかれさまでした。これでチップ計算アプリは完成です。成し遂げた成果を誇りに思ってください。ここで学習したことが、もっと優れた外観と機能を持つアプリを作成するための足掛かりとなることを願っています。

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

5743ac5ee2493d7.png ab4acfeed8390465.png

この Codelab のコードを取得して Android Studio で開くには、以下の手順に沿って操作します。

コードを取得する

  1. 指定された URL をクリックします。プロジェクトの GitHub ページがブラウザで開きます。
  2. プロジェクトの GitHub ページで、[Code] ボタンをクリックすると、ダイアログが表示されます。

Eme2bJP46u-pMpnXVfm-bS2N2dlyq6c0jn1DtQYqBaml7TUhzXDWpYoDI0lGKi4xndE_uJw8sKfwfOZ1fC503xCVZrbh10JKJ4iEHdLDwFfdvnOheNxkokITW1LW6UZTncVJJUZ5Fw

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

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

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

Tdjf5eS2nCikM9KdHgFaZNSbIUCzKXP6WfEaKVE2Oz1XIGZhgTJYlaNtXTHPFU1xC9pPiaD-XOPdIxVxwZAK8onA7eJyCXz2Km24B_8rpEVI_Po5qlcMNN8s4Tkt6kHEXdLQTDW7mg

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

PaMkVnfCxQqSNB1LxPpC6C6cuVCAc8jWNZCqy5tDVA6IO3NE2fqrfJ6p6ggGpk7jd27ybXaWU7rGNOFi6CvtMyHtWdhNzdAHmndzvEdwshF_SG24Le01z7925JsFa47qa-Q19t3RxQ

  1. [Import Project] ダイアログで、展開したプロジェクト フォルダがある場所([ダウンロード] フォルダなど)に移動します。
  2. そのプロジェクト フォルダをダブルクリックします。
  3. Android Studio でプロジェクトが開かれるまで待ちます。
  4. 実行ボタン j7ptomO2PEQNe8jFt4nKCOw_Oc_Aucgf4l_La8fGLCMLy0t9RN9SkmBFGOFjkEzlX4ce2w2NWq4J30sDaxEe4MaSNuJPpMgHxnsRYoBtIV3-GUpYYcIvRJ2HrqR27XGuTS4F7lKCzg をクリックして、アプリをビルドし、実行します。期待どおりに動作することを確認します。
  5. [Project] ツール ウィンドウでプロジェクト ファイルを表示して、アプリがどのように実装されているかを確認します。
  • マテリアル デザイン ガイドラインに沿って可能な限りマテリアル デザイン コンポーネントを使用し、カスタマイズを検討します。
  • アイコンを追加することにより、アプリの各要素がどのように機能するかについてユーザーに視覚的な手掛かりを与えます。
  • ConstraintLayout を使用してレイアウト内に要素を配置します。
  • エッジケース(例: デバイスを回転させて横向きの画面にアプリを表示する)でアプリをテストし、必要に応じて改善します。
  • コードにコメントを挿入して、他の人がコードを読んだときに作成者の意図を簡単に理解できるようにします。
  • コードを再フォーマットしてクリーンアップを行い、コードをできるだけ簡潔にします。
  • 前の Codelab からの続きとして、ここで学習したベスト プラクティス(マテリアル デザイン コンポーネントの使用方法など)を使い、マテリアル ガイドラインにもっと近づけるように単位変換クッキング アプリを更新してください。