Kotlin Android の基礎 10.3: 全ユーザー対象の設計

この Codelab は、Android Kotlin の基礎コースの一部です。このコースを最大限に活用するには、Codelab を順番に進めることをおすすめします。コースのすべての Codelab は、Android Kotlin の基礎の Codelab のランディング ページに一覧表示されています。

はじめに

趣味で開発する場合でも、ビジネス目的で開発する場合でも、できるだけ多くのユーザーがアプリを利用できるようにすることは理にかなっています。それを達成するには、複数の側面があります。

  • RTL 言語をサポートします。ヨーロッパの言語をはじめ、多くの言語は左から右に読みます。これらの言語を対象とするアプリは、通常、これらの言語に合うように設計されています。アラビア語など、右から左に読む言語は他にもたくさんあります。右から左に記述する(RTL)言語に対応したアプリを作成して、潜在的なユーザーを増やしましょう。
  • ユーザー補助機能をスキャンします。他のユーザーがアプリをどのように利用するかを推測することはできますが、落とし穴があります。 ユーザー補助検証ツール アプリは、推測を必要としないループでアプリを分析し、ユーザー補助機能を改善できる箇所を特定します。
  • コンテンツの説明を使用して TalkBack 向けに設計します。視覚障がいのあるユーザーは、想像以上に多く、盲目のユーザーだけでなく、多くのユーザーがスクリーン リーダーを使用しています。コンテンツの説明は、ユーザーが画面の要素を操作したときにスクリーン リーダーが読み上げるフレーズです。
  • 夜間モードをサポート。視覚障がいのあるユーザーの多くにとって、画面の色を変更するとコントラストが改善され、アプリを視覚的に操作しやすくなります。Android ではナイトモードを簡単にサポートできるため、ユーザーがデフォルトの画面の色を簡単に変更できるように、常にナイトモードをサポートする必要があります。

この Codelab では、これらのオプションをそれぞれ確認し、GDG Finder アプリにサポートを追加します。

また、Android アプリでチップを使用する方法も学習します。チップを使用すると、アプリのアクセシビリティを維持しながら、アプリをより魅力的なものにすることができます。

前提となる知識

以下について把握しておく必要があります。

  • アクティビティとフラグメントを持つアプリを作成し、データを渡しながらフラグメント間を移動する方法。
  • ビューとビュー グループ(特に RecyclerView)を使用してユーザー インターフェースをレイアウトする。
  • 推奨アーキテクチャで ViewModel などのアーキテクチャ コンポーネントを使用して、構造が整った効率的なアプリを作成する方法。
  • データ バインディング、コルーチン、マウスのクリックの処理方法。
  • Room データベースを使用してインターネットに接続し、データをローカルでキャッシュに保存する方法。
  • ビューのプロパティの設定方法、XML リソース ファイルへのリソースの抽出方法、XML リソース ファイルからのリソースの使用方法。
  • スタイルとテーマを使用してアプリの外観をカスタマイズする方法。
  • マテリアル コンポーネント、ディメンション リソース、カスタム カラーリングの使用方法。

学習内容

  • できるだけ多くのユーザーがアプリを利用できるようにする方法。
  • 右から左に記述する(RTL)言語に対応したアプリを作成する方法。
  • アプリのユーザー補助機能を評価する方法。
  • コンテンツの説明を使用して、スクリーン リーダーでアプリをより適切に動作させる方法。
  • チップの使用方法。
  • アプリをダークモードに対応させる方法。

演習内容

  • 指定されたアプリを評価し、RTL 言語に対応させることでユーザー補助機能を改善します。
  • アプリをスキャンして、ユーザー補助機能を改善できる箇所を特定します。
  • 画像にコンテンツの説明を使用します。
  • ドローアブルの使用方法について説明します。
  • アプリにナイトモードを使用する機能を追加します。

GDG 検索スターター アプリは、このコースでこれまで学んだことをすべて活用して構築されています。

アプリは ConstraintLayout を使用して 3 つの画面をレイアウトします。2 つの画面は、Android での色とテキストを調べるために使用するレイアウト ファイルです。

3 つ目の画面は GDG ファインダーです。GDG(Google デベロッパー グループ)は、Android などの Google テクノロジーに焦点を当てたデベロッパーのコミュニティです。世界各地の GDG が、ミートアップ、カンファレンス、スタディ ジャムなどのイベントを開催しています。

このアプリを開発する際は、GDG の実際のリストを使用します。ファインダー画面では、デバイスの位置情報を使用して GDG を距離順に並べ替えます。

お住まいの地域に GDG がある場合は、ウェブサイトでイベントを確認して登録できます。GDG イベントは、他の Android デベロッパーと出会い、このコースでは取り上げなかった業界のベスト プラクティスを学ぶ絶好の機会です。

以下のスクリーンショットは、この Codelab の最初から最後までアプリがどのように変化するかを示しています。

左から右(LTR)言語と右から左(RTL)言語の主な違いは、表示されるコンテンツの方向です。UI の方向が LTR から RTL に(またはその逆に)変更されることは、ミラーリングと呼ばれることがよくあります。ミラーリングは、テキスト、テキスト フィールドのアイコン、レイアウト、方向を示すアイコン(矢印など)を含む画面の大部分に影響します。数字(時計、電話番号)、方向のないアイコン(機内モード、Wi-Fi)、再生コントロール、ほとんどのグラフなど、その他のアイテムはミラーリングされません。

RTL テキスト方向を使用する言語は、世界中で 10 億人以上が使用しています。Android デベロッパーは世界中にいるため、GDG Finder アプリは RTL 言語をサポートする必要があります。

ステップ 1: RTL サポートを追加する

このステップでは、GDG Finder アプリが RTL 言語に対応するようにします。

  1. この Codelab のスターター アプリである GDGFinderMaterial アプリをダウンロードして実行するか、前の Codelab の最終コードから続行します。
  2. Android マニフェストを開きます。
  3. <application> セクションで、アプリが RTL をサポートすることを指定する次のコードを追加します。
<application
        ...
        android:supportsRtl="true">
  1. [Design] タブで activity_main.xml を開きます。
  2. [プレビューの言語 / 地域] プルダウン メニューから [右から左へのプレビュー] を選択します。(このメニューが見つからない場合は、ペインを広げるか、[属性] ペインを閉じて表示します)。

  1. プレビューで、ヘッダー「GDG Finder」が右に移動し、画面の残りの部分はほぼ同じになっていることを確認します。全体的に、この画面は合格です。しかし、テキストビューの配置は右揃えではなく左揃えになっているため、正しくありません。

  1. デバイスでこれを機能させるには、デバイスまたはエミュレータの [設定] の [開発者向けオプション] で [RTL レイアウトを使用] を選択します。(デベロッパー オプションをオンにする必要がある場合は、[ビルド番号] を見つけて、デベロッパーであることを示すトーストが表示されるまでクリックします。これは、デバイスや Android システムのバージョンによって異なります)。

  1. アプリを実行し、デバイスでメイン画面が [プレビュー] と同じように表示されることを確認します。FAB が左に、ハンバーガー メニューが右に切り替わりました。
  2. アプリでナビゲーション ドロワーを開き、[検索] 画面に移動します。下の図のように、アイコンは左側に表示され、テキストは表示されません。テキストは画面外のアイコンの左側に表示されていることがわかりました。これは、コードでビューのプロパティとレイアウト制約に左右の画面参照を使用しているためです。

ステップ 2: left と right の代わりに start と end を使用する

テキストの方向が変わっても、画面上の「左」と「右」(画面に向かって)は変わりません。たとえば、layout_constraintLeft_toLeftOf は常に要素の左側を画面の左側に制約します。アプリのケースでは、上のスクリーンショットに示すように、RTL 言語でテキストが画面外に表示されています。

この問題を解決するには、「左」と「右」ではなく、StartEnd という用語を使用します。この用語は、現在の言語のテキストの方向に応じてテキストの開始位置と終了位置を適切に設定し、マージンとレイアウトが画面の正しい領域に表示されるようにします。

  1. Open list_item.xml
  2. LeftRight への参照を、StartEnd への参照に置き換えます。
app:layout_constraintStart_toStartOf="parent"

app:layout_constraintStart_toEndOf="@+id/gdg_image"
app:layout_constraintEnd_toEndOf="parent"
  1. ImageViewlayout_marginLeftlayout_marginStart に置き換えます。これにより、アイコンが画面の端から離れるように、余白が正しい位置に移動します。
<ImageView
android:layout_marginStart="
?
  1. fragment_gdg_list.xml を開きます。[プレビュー] ペインで GDG のリストを確認します。アイコンはミラーリングされているため、まだ間違った方向を向いています(アイコンがミラーリングされていない場合は、右から左へのプレビューが表示されていることを確認してください)。マテリアル デザインのガイドラインによると、アイコンはミラーリングすべきではありません。
  2. res/drawable/ic_gdg.xml を開きます。
  3. XML コードの最初の行で android:autoMirrored="true" を見つけて削除し、ミラーリングを無効にします。
  4. [プレビュー] を確認するか、アプリを再度実行して [Search GDG] 画面を開きます。これでレイアウトが修正されました。

ステップ 3: Android Studio に処理を任せる

前の演習では、RTL 言語をサポートするための最初のステップを行いました。幸いなことに、Android Studio はアプリをスキャンして、多くの基本設定を自動的に行うことができます。

  1. list_item.xmlTextView で、layout_marginStartlayout_marginLeft に戻して、スキャナが検索対象を見つけられるようにします。
<TextView
android:layout_marginLeft="@dimen/spacing_normal"
  1. Android Studio で、[Refactor] > [Add RTL support where possible] を選択し、マニフェストとレイアウト ファイルを更新して start プロパティと end プロパティを使用するためのチェックボックスをオンにします。

  1. [リファクタリングのプレビュー] ペインで、[app] フォルダを見つけ、すべての詳細が開くまで展開します。
  2. アプリフォルダの下に、先ほど変更した layout_marginLeft がリファクタリングするコードとしてリストされていることに注目してください。

  1. プレビューにはシステム ファイルとライブラリ ファイルも表示されます。layout、layout-watch-v20app に含まれていないその他のフォルダを右クリックし、コンテキスト メニューから [除外] を選択します。

  1. では、今すぐリファクタリングを行いましょう。(システム ファイルに関するポップアップが表示された場合は、アプリコードの一部ではないフォルダをすべて除外していることを確認してください)。
  1. layout_marginLeftlayout_marginStart に戻っていることに注意してください。

ステップ 3: ロケールのフォルダを調べる

これまでは、アプリで使用されるデフォルト言語の方向を変更しただけです。本番環境のアプリでは、strings.xml ファイルを翻訳者に送信して、新しい言語に翻訳してもらいます。この Codelab では、アプリはスペイン語の strings.xml ファイルを提供します(翻訳の生成には Google 翻訳を使用しているため、完璧ではありません)。

  1. Android Studio で、プロジェクト ビューを [Project Files] に切り替えます。
  2. res フォルダを開き、res/valuesres/values-es のフォルダを確認します。フォルダ名の「es」は、スペイン語の言語コードです。values-"言語コード" フォルダには、サポートされている各言語の値が含まれています。拡張子のない values フォルダには、それ以外の場合に適用されるデフォルトのリソースが含まれています。

  1. values-esstrings.xml を開くと、すべての文字列がスペイン語になっていることがわかります。
  2. Android Studio で、[デザイン] タブの activity_main.xml を開きます。
  3. [Locale for Preview] プルダウンで [Spanish] を選択します。テキストがスペイン語で表示されます。

  1. [省略可] RTL 言語に精通している場合は、その言語で values フォルダと strings.xml を作成し、デバイスでの表示をテストします。
  2. [省略可] デバイスの言語設定を変更して、アプリを実行します。デバイスを読めない言語に変更しないようにしてください。変更すると元に戻すのが少し難しくなります。

前のタスクでは、アプリを手動で変更し、Android Studio を使用して、RTL をさらに改善できる点を確認しました。

アプリのユーザー補助機能を強化するうえで、ユーザー補助検証ツールアプリは最適なツールです。対象デバイスでアプリをスキャンし、タップ ターゲットを大きくする、コントラストを強める、画像の説明を追加するなど、アプリのユーザー補助機能を改善するための提案を行います。ユーザー補助検証ツールは Google が作成したもので、Play ストアからインストールできます。

ステップ 1: ユーザー補助検証ツールをインストールして実行する

  1. Google Play ストアを開き、必要に応じてログインします。この操作は、実機またはエミュレータで行うことができます。この Codelab では、emulator を使用します。
  1. Play ストアで Google LLC のユーザー補助検証ツールを検索します。スキャンには多くの権限が必要になるため、Google が発行した正しいアプリを入手してください。

  1. エミュレータにスキャナをインストールします。
  2. インストールが完了したら、[開く] をクリックします。
  3. [Get Started] をクリックします。
  4. [OK] をクリックして、設定でユーザー補助検証ツールの設定を開始します。

  1. [ユーザー補助検証ツール] をクリックして、デバイスの [ユーザー補助] 設定に移動します。

  1. [サービスを使用] をクリックして有効にします。

  1. 画面上の指示に沿って操作し、すべての権限を付与します。
  2. [OK Got it] をクリックして、ホーム画面に戻ります。画面のどこかに青いチェックマークのボタンが表示されることがあります。このボタンをクリックすると、フォアグラウンドのアプリのテストがトリガーされます。ボタンはドラッグして位置を変更できます。このボタンはどのアプリよりも上に表示されるため、いつでもテストを開始できます。

  1. アプリを開くか、実行します。
  2. 青いボタンをクリックし、追加のセキュリティ警告と権限を承認します。

ユーザー補助機能スキャナのアイコンを初めてクリックすると、画面に表示されているすべての情報を取得する権限を求めるメッセージが表示されます。これは非常に恐ろしい権限のように思えますが、実際そのとおりです。

このような権限は、アプリがメールを読んだり、銀行口座情報を取得したりする可能性があるため、付与しないようにしてください。ただし、ユーザー補助スキャナが動作するには、ユーザーがアプリを操作するのと同じようにアプリを検査する必要があります。そのため、この権限が必要になります。

  1. 青色のボタンをクリックし、分析が完了するまで待ちます。次のスクリーンショットのように、タイトルと FAB が赤いボックスで囲まれて表示されます。この画面でユーザー補助機能を改善するための提案が 2 つあることを示します。

  1. GDG Finder を囲むボックスをクリックします。次の図に示すように、追加情報を含むペインが開き、画像のコントラストに関する問題が示されます。
  2. [ 画像のコントラスト] の情報を展開すると、ツールが解決策を提案します。
  3. 右側の矢印をクリックすると、次の項目の情報が表示されます。

  1. アプリで [Apply for GDG] 画面に移動し、ユーザー補助検証ツール アプリでスキャンします。下の左の図のように、多くの提案が表示されます。正確には 12 個です。公平を期すために言っておくと、類似アイテムの重複もあります。
  2. 下の右側のスクリーンショットに示すように、下部のツールバーにある「スタック」アイコン をクリックすると、すべての候補のリストが表示されます。この Codelab では、これらの問題にすべて対処します。

Google のアプリ集である Android ユーザー補助設定ツールには、アプリのユーザー補助機能を強化するためのツールが含まれています。TalkBack などのツールが含まれています。TalkBack は、音声、触覚、音声フィードバックを提供するスクリーン リーダーです。これにより、ユーザーは画面を見ずにデバイスのコンテンツを操作したり、利用したりできます。

TalkBack は、目の不自由な方だけでなく、何らかの視覚障がいのある多くの方にも利用されていることがわかりました。目を休ませたいだけの人もいます。

つまり、ユーザー補助はすべてのユーザーのための機能なのです。このタスクでは、TalkBack を試して、TalkBack で適切に動作するようにアプリを更新します。

ステップ 1: ユーザー補助設定ツールをインストールして実行する

TalkBack は多くの実機にプリインストールされていますが、エミュレータではインストールする必要があります。

  1. Google Play ストアを開きます。
  2. [ユーザー補助設定ツール] を探します。Google の正しいアプリであることを確認してください。
  3. インストールされていない場合は、ユーザー補助機能スイートをインストールします。
  4. デバイスで TalkBack を有効にするには、[設定] > [ユーザー補助] に移動し、[サービスを使用] を選択して TalkBack をオンにします。ユーザー補助スキャナと同様に、TalkBack が画面上のコンテンツを読み取るには権限が必要です。権限リクエストを承認すると、TalkBack の使い方を効果的に学ぶためのチュートリアル リストが表示されます。
  5. ここで一時停止して、チュートリアルをご覧ください。チュートリアルでは、終了後に TalkBack をオフにする方法を学ぶことができます。
  6. チュートリアルを終了するには、[戻る] ボタンをクリックして選択し、画面上の任意の場所をダブルタップします。
  1. TalkBack を使用して GDG Finder アプリを探索します。TalkBack が画面やコントロールに関する有用な情報を提供しない場所を特定します。これは次の演習で修正します。

ステップ 2: コンテンツの説明を追加する

コンテンツ記述子は、ビューの意味を説明する説明ラベルです。ほとんどのビューにコンテンツの説明を設定する必要があります。

  1. GDG Finder アプリを実行し、TalkBack を有効にした状態で、[Apply to run GDG](GDG の運営に申し込む)画面に移動します。
  2. メイン画像をタップしても何も起こりません。
  3. add_gdg_fragment.xml を開きます。
  4. 以下に示すように、ImageView にコンテンツ記述子属性を追加します。stage_image_description 文字列は strings.xml で提供されています。
android:contentDescription="@string/stage_image_description"
  1. アプリを実行します。
  2. [Apply to run GDG] に移動して、画像をクリックします。画像の簡単な説明が読み上げられます。
  3. [省略可] このアプリの他の画像の内容説明を追加します。本番環境のアプリでは、すべての画像に内容説明が必要です。

ステップ 3: 編集可能なテキスト フィールドにヒントを追加する

EditText などの編集可能な要素では、XML で android:hint を使用して、ユーザーが入力する内容を把握できるようにすることができます。ヒントは、入力フィールドのデフォルトのテキストであるため、常に UI に表示されます。

  1. 引き続き add_gdg_fragment.xml で作業します。
  2. 次のコードを参考に、コンテンツの説明とヒントを追加します。

textViewIntro に追加します。

android:contentDescription="@string/add_gdg"

それぞれ編集テキストに追加します。

android:hint="@string/your_name_label"

android:hint="@string/email_label"

android:hint="@string/city_label"

android:hint="@string/country_label"

android:hint="@string/region_label"
  1. labelTextWhy にコンテンツの説明を追加します。
android:contentDescription="@string/motivation" 
  1. EditTextWhy にヒントを追加します。編集ボックスにラベルを付けたら、ラベルにコンテンツの説明を追加し、ボックスにヒントを追加します。
android:hint="@string/enter_motivation"
  1. 送信ボタンの内容説明を追加します。すべてのボタンには、押すとどうなるかの説明が必要です。
android:contentDescription="@string/submit_button_description"
  1. TalkBack を有効にしてアプリを実行し、GDG の運営を申請するためのフォームに記入します。

ステップ 4: コンテンツ グループを作成する

TalkBack でグループとして扱う必要がある UI コントロールには、コンテンツ グループ化を使用できます。グループ化された関連コンテンツは、まとめてお知らせします。これにより、支援技術のユーザーは、画面上のすべての情報を確認するために、スワイプ、スキャン、待機を頻繁に行う必要がなくなります。画面上のコントロールの表示には影響しません。

UI コンポーネントをグループ化するには、LinearLayout などの ViewGroup でラップします。GDG Finder アプリでは、labelTextWhy 要素と editTextWhy 要素は意味的に関連しているため、グループ化の候補として最適です。

  1. add_gdg_fragment.xml を開きます。
  2. LabelTextWhyEditTextWhyLinearLayout で囲んでコンテンツ グループを作成します。以下のコードをコピーして貼り付けます。この LinearLayout には、必要なスタイルのいくつかがすでに含まれています。(buttonLinearLayout の外側にあることを確認してください)。
<LinearLayout android:id="@+id/contentGroup" android:layout_width="match_parent"
            android:layout_height="wrap_content" android:focusable="true"
            app:layout_constraintTop_toBottomOf="@id/EditTextRegion"
            android:orientation="vertical" app:layout_constraintStart_toStartOf="@+id/EditTextRegion"
            app:layout_constraintEnd_toEndOf="@+id/EditTextRegion"
            android:layout_marginTop="16dp" app:layout_constraintBottom_toTopOf="@+id/button"
            android:layout_marginBottom="8dp">

     <!-- label and edit text here –>

<LinearLayout/>
  1. [Code] > [Reformat code] を選択して、すべてのコードを適切にインデントします。
  2. labelTextWhyeditTextWhy からすべてのレイアウト マージンを削除します。
  3. labelTextWhy で、layout_constraintTop_toTopOf 制約を contentGroup に変更します。
app:layout_constraintTop_toTopOf="@+id/contentGroup" />
  1. editTextWhy で、layout_constraintBottom_toBottomOf 制約を contentGroup に変更します。
app:layout_constraintBottom_toBottomOf="@+id/contentGroup"
  1. EditTextRegionButtoncontentGroup に制約して、エラーを解消します。
app:layout_constraintBottom_toTopOf="@+id/contentGroup"
  1. LinearLayout に余白を追加します。必要に応じて、このマージンをディメンションとして抽出します。
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"

サポートが必要な場合は、解答コードの add_gdg_fragment.xml とご自身のコードを比較してください。

  1. アプリを実行し、TalkBack で [Apply to run GDG] 画面を操作します。

ステップ 5: ライブ リージョンを追加する

現在、送信ボタンのラベルは [OK] です。フォームが送信される前にボタンに 1 つのラベルと説明があり、ユーザーがクリックしてフォームが送信された後に別のラベルとコンテンツの説明に動的に変更される方が望ましいでしょう。ライブ リージョンを使用すると、この処理を行うことができます。

ライブ リージョンは、ビューが変更されたときにユーザーに通知するかどうかをユーザー補助サービスに示します。たとえば、パスワードが間違っていることやネットワーク エラーが発生していることをユーザーに知らせることは、アプリのアクセシビリティを高める優れた方法です。この例では、簡略化のため、送信ボタンの状態が変化したときにユーザーに通知します。

  1. add_gdg_fragment.xml を開きます。
  2. 指定された submit 文字列リソースを使用して、ボタンのテキストの割り当てを Submit に変更します。
android:text="@string/submit"
  1. android:accessibilityLiveRegion 属性を設定して、ボタンにライブ リージョンを追加します。入力する値には、いくつかのオプションがあります。変更の重要度に応じて、ユーザーを中断するかどうかを選択できます。値が「assertive」の場合、ユーザー補助サービスは進行中の音声読み上げを中断して、このビューの変更をすぐにアナウンスします。値を「none」に設定すると、変更はアナウンスされません。「丁寧」に設定すると、ユーザー補助サービスは変更を通知しますが、順番を待ちます。値を「polite」に設定します。

android:accessibilityLiveRegion="polite"
  1. add パッケージで、AddGdgFragment.kt を開きます。
  2. showSnackBarEvent Observer の中で、SnackBar の表示が終わったら、ボタンの新しいコンテンツの説明とテキストを設定します。
binding.button.contentDescription=getString(R.string.submitted)
binding.button.text=getString(R.string.done)
  1. アプリを実行してボタンをクリックします。残念ながら、ボタンとフォントが小さすぎます。

ステップ 6: ボタンのスタイルを修正する

  1. add_gdg_fragment.xml で、ボタンの widthheightwrap_content に変更して、ラベル全体が表示され、ボタンが適切なサイズになるようにします。
android:layout_width="wrap_content"
android:layout_height="wrap_content"
  1. アプリでより優れたテーマ スタイルを使用できるように、ボタンから backgroundTinttextColortextSize 属性を削除します。
  2. textViewIntro から textColor 属性を削除します。テーマの色は、十分なコントラストを提供する必要があります。
  3. アプリを実行します。[送信] ボタンが使いやすくなっていることがわかります。[送信] をクリックすると、[完了] に変わります。

チップは、属性、テキスト、エンティティ、アクションを表すコンパクトな要素です。ユーザーが情報を入力したり、選択肢を選択したり、コンテンツをフィルタしたり、アクションをトリガーしたりできます。

Chip ウィジェットは、すべてのレイアウトと描画ロジックを含む ChipDrawable の周囲の薄いビュー ラッパーです。この追加のロジックは、タッチ、マウス、キーボード、ユーザー補助機能のナビゲーションをサポートするために存在します。メインチップと閉じるアイコンは、別々の論理サブビューと見なされ、独自のナビゲーション動作と状態を含みます。

チップはドローアブルを使用します。Android のドローアブルを使用すると、画面に画像、図形、アニメーションを描画できます。サイズを固定することも、動的にサイズ変更することもできます。GDG アプリの画像のように、画像を描画可能オブジェクトとして使用できます。また、ベクター ドローイングを使用して、想像できるものを何でも描画できます。この Codelab では扱いませんが、サイズ変更可能なドローアブルとして 9 パッチ ドローアブルもあります。drawable/ic_gdg.xml の GDG ロゴも別のドローアブルです。

ドローアブルはビューではないため、ConstraintLayout の中に直接配置することはできません。ImageView の中に配置する必要があります。また、テキスト ビューやボタンの背景としてドローアブルを使用することもできます。この場合、背景はテキストの背後に描画されます。

ステップ 1: GDG のリストにチップを追加する

下のチェック済みのチップでは、3 つのドローアブルを使用しています。背景とチェックマークはそれぞれドローアブルです。チップをタップすると、リップル効果が作成されます。これは、状態の変化に応じてリップル効果を表示する特別な RippleDrawable を使用して行われます。

このタスクでは、GDG のリストにチップを追加し、選択されたときに状態が変化するようにします。この演習では、検索画面の上部に「チップ」と呼ばれるボタンの行を追加します。各ボタンは GDG リストをフィルタし、ユーザーには選択した地域の検索結果のみが表示されます。ボタンを選択すると、ボタンの背景が変わり、チェックマークが表示されます。

  1. fragment_gdg_list.xml を開きます。
  2. HorizontalScrollView. 内に com.google.android.material.chip.ChipGroup を作成します。singleLine プロパティを true に設定して、すべてのチップが水平方向にスクロール可能な 1 行に並ぶようにします。singleSelection プロパティを true に設定して、グループ内のチップを一度に 1 つだけ選択できるようにします。コードは次のとおりです。
<com.google.android.material.chip.ChipGroup
    android:id="@+id/region_list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:singleSelection="true"
    android:padding="@dimen/spacing_normal"/>
  1. layout フォルダに、1 つの Chip のレイアウトを定義するための region.xml という新しいレイアウト リソース ファイルを作成します。
  2. region.xml で、すべてのコードを次の 1 つの Chip のレイアウトに置き換えます。この Chip はマテリアル コンポーネントです。また、プロパティ app:checkedIconVisible を設定することでチェックマークが表示されることにも注目してください。selected_highlight 色がないため、エラーが発生します。
<?xml version="1.0" encoding="utf-8"?>

<com.google.android.material.chip.Chip
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@style/Widget.MaterialComponents.Chip.Choice"
        app:chipBackgroundColor="@color/selected_highlight"
        app:checkedIconVisible="true"
        tools:checked="true"/>
  1. 不足している selected_highlight カラーを作成するには、selected_highlight にカーソルを置き、インテンション メニューを表示して、選択したハイライトのカラーリソースを作成します。デフォルトのオプションのままで構わないため、[OK] をクリックします。ファイルは res/color フォルダに作成されます。
  2. res/color/selected_highlight.xml を開きます。<selector> としてエンコードされたこの色状態リストでは、状態ごとに異なる色を指定できます。各状態と関連する色は <item> としてエンコードされます。これらの色の詳細については、カラー テーマをご覧ください。
  1. <selector> 内で、デフォルトの色 colorOnSurface を持つアイテムを状態リストに追加します。状態リストでは、常にすべての状態を網羅することが重要です。その 1 つの方法は、デフォルトの色を設定することです。
<item android:alpha="0.18" android:color="?attr/colorOnSurface"/>
  1. デフォルトの色の上の行に、colorPrimaryVariant の色で item を追加し、選択された状態が true の場合にのみ使用されるように制約します。状態リストは、case ステートメントのように上から下に処理されます。どの状態にも一致しない場合は、デフォルトの状態が適用されます。
<item android:color="?attr/colorPrimaryVariant"
         android:state_selected="true" />

ステップ 2: チップの行を表示する

GDG アプリは、GDG がある地域を示すチップのリストを作成します。チップを選択すると、アプリは結果をフィルタして、その地域の GDG の結果のみを表示します。

  1. search パッケージで、GdgListFragment.kt を開きます。
  2. onCreateView() で、return ステートメントのすぐ上に viewModel.regionList のオブザーバーを追加し、onChanged() をオーバーライドします。ビューモデルによって提供されるリージョンのリストが変更された場合は、チップを再作成する必要があります。指定された datanull の場合、すぐに戻るステートメントを追加します。
viewModel.regionList.observe(viewLifecycleOwner, object: Observer<List<String>> {
        override fun onChanged(data: List<String>?) {
             data ?: return
        }
})
  1. onChanged() 内で、null テストの下に binding.regionListchipGroup という新しい変数に割り当てて regionList をキャッシュに保存します。
val chipGroup = binding.regionList
  1. 以下では、chipGroup.context からチップを拡張するための新しい layoutInflator を作成します。
val inflator = LayoutInflater.from(chipGroup.context)
  1. プロジェクトをクリーンアップして再ビルドし、データバインディング エラーを解消します。

インフレーターの下に、実際のチップを作成します。regionList の各リージョンに 1 つずつ作成します。

  1. すべてのチップを保持する変数 children を作成します。渡された data にマッピング関数を割り当てて、各チップを作成して返します。
val children = data.map {} 
  1. マップ ラムダ内で、各 regionName に対してチップを作成して拡張します。完成したコードは次のとおりです。
val children = data.map {
   val children = data.map { regionName ->
       val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
       chip.text = regionName
       chip.tag = regionName
       // TODO: Click listener goes here.
       chip
   }
}
  1. ラムダ内で、chip を返す直前にクリック リスナーを追加します。chip がクリックされたら、状態を checked に設定します。viewModelonFilterChanged() を呼び出します。これにより、このフィルタの結果を取得する一連のイベントがトリガーされます。
chip.setOnCheckedChangeListener { button, isChecked ->
   viewModel.onFilterChanged(button.tag as String, isChecked)
}
  1. ラムダの最後に、chipGroup から現在のビューをすべて削除し、children から chipGroup にすべてのチップを追加します。(チップは更新できないため、chipGroup の内容を削除して再作成する必要があります)。
chipGroup.removeAllViews()

for (chip in children) {
   chipGroup.addView(chip)
}

完成したオブザーバーは次のようになります。

   override fun onChanged(data: List<String>?) {
       data ?: return

       val chipGroup = binding.regionList
       val inflator = LayoutInflater.from(chipGroup.context)

       val children = data.map { regionName ->
           val chip = inflator.inflate(R.layout.region, chipGroup, false) as Chip
           chip.text = regionName
           chip.tag = regionName
           chip.setOnCheckedChangeListener { button, isChecked ->
               viewModel.onFilterChanged(button.tag as String, isChecked)
           }
           chip
       }
       chipGroup.removeAllViews()

       for (chip in children) {
           chipGroup.addView(chip)
       }
   }
})
  1. アプリを実行し、GDGS を検索して [検索] 画面を開き、新しいチップを使用します。各チップをクリックすると、その下にフィルタ グループが表示されます。

夜間モードでは、デバイスの設定で夜間モードが有効になっている場合などに、アプリのカラーをダークテーマに変更できます。夜間モードでは、アプリのデフォルトの明るい背景が暗い背景に変更され、他のすべての画面要素もそれに応じて変更されます。

ステップ 1: 夜間モードを有効にする

アプリにダークテーマを提供するには、テーマを Light テーマから DayNight というテーマに変更します。DayNight テーマは、モードに応じて明るく表示されたり暗く表示されたりします。

  1. styles.xml, で、AppTheme 親テーマを Light から DayNight に変更します。
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
  1. MainActivityonCreate() メソッドで、AppCompatDelegate.setDefaultNightMode() を呼び出して、プログラムでダークモードをオンにします。
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
  1. アプリを実行し、ダークモードに切り替わっていることを確認します。

ステップ 2: 独自のダークモード カラーパレットを生成する

ダークモードをカスタマイズするには、ダークモードで使用する -night 修飾子を含むフォルダを作成します。たとえば、values-night というフォルダを作成することで、夜間モードで特定の色を使用できます。

  1. material.io のカラー選択ツールにアクセスして、夜間モードのカラーパレットを作成します。たとえば、濃い青色をベースにすることができます。
  2. colors.xml ファイルを生成してダウンロードします。
  3. [Project Files] ビューに切り替えて、プロジェクト内のすべてのフォルダを一覧表示します。
  4. [res] フォルダを見つけて展開します。
  5. res/values-night リソース フォルダを作成します。
  6. 新しい colors.xml ファイルを res/values-night リソース フォルダに追加します。
  7. アプリを実行します。ナイトモードは有効のままです。アプリは res/values-night で定義した新しい色を使用します。チップで新しいセカンダリ カラーが使用されていることに注目してください。

Android Studio プロジェクト: GDGFinderFinal

RTL 言語をサポート

  • Android マニフェストで android:supportsRtl="true" を設定します。
  • エミュレータで RTL をプレビューし、独自の言語を使用して画面レイアウトを確認できます。デバイスまたはエミュレータで、[設定] を開き、[開発者向けオプション] で [RTL レイアウトを使用] を選択します。
  • LeftRight への参照を StartEnd への参照に置き換えます。
  • android:autoMirrored="true" を削除して、ドローアブルのミラーリングを無効にします。
  • [Refactor] > [Add RTL support where possible] を選択して、Android Studio に処理を任せます。
  • values-"言語コード" フォルダを使用して、言語固有のリソースを保存します。

ユーザー補助をスキャンする

コンテンツの説明を使用して TalkBack 向けに設計する

  • Google の Android ユーザー補助設定ツールをインストールします。これには TalkBack が含まれています。
  • すべての UI 要素にコンテンツの説明を追加します。例:
    android:contentDescription="@string/stage_image_description"
  • EditText などの編集可能な要素の場合は、XML で android:hint 属性を使用して、入力する内容に関するヒントをユーザーに提供します。
  • 関連する要素をビューグループにラップして、コンテンツ グループを作成します。
  • android:accessibilityLiveRegion を使用してライブ リージョンを作成し、ユーザーに追加のフィードバックを提供します。

チップを使用してフィルタを実装する

  • チップは、属性、テキスト、エンティティ、アクションを表すコンパクトな要素です。
  • チップのグループを作成するには、com.google.android.material.chip.ChipGroup を使用します。
  • 1 つの com.google.android.material.chip.Chip のレイアウトを定義します。
  • チップの色を変更する場合は、状態付きの色を含む <selector> として色状態リストを指定します。
    <item android:color="?attr/colorPrimaryVariant"
    android:state_selected="true" />
  • ビューモデルのデータにオブザーバーを追加して、チップをライブデータにバインドします。
  • チップを表示するには、チップグループのインフレータを作成します。
    LayoutInflater.from(chipGroup.context)
  • チップを作成し、目的のアクションをトリガーするクリック リスナーを追加して、チップをチップ グループに追加します。

ダークモードをサポートする

  • DayNight AppTheme を使用してダークモードをサポートします。
  • ダークモードはプログラムで設定できます。
    AppCompatDelegate.setDefaultNightMode()
  • res/values-night リソース フォルダを作成して、ダークモード用のカスタムカラーと値を指定します。

Android デベロッパー ドキュメント:

その他のリソース:

このセクションでは、インストラクター主導のコースの一環として、この Codelab に取り組んでいる生徒向けに考えられる宿題をいくつか示します。インストラクターは、以下のようなことを行えます。

  • 必要に応じて宿題を与える
  • 宿題の提出方法を生徒に伝える
  • 宿題を採点する

インストラクターは、これらの提案を必要なだけ使用し、必要に応じて他の宿題も自由に与えることができます。

この Codelab に独力で取り組む場合は、これらの宿題を自由に使用して知識をテストしてください。

問題 1

RTL 言語をサポートするために必要なことは次のうちどれですか。

▢ プロパティの LeftRightStartEnd に置き換えます

▢ RTL 言語に切り替えること

▢ すべてのアイコンに android:autoMirrored="true" を使用すること

▢ コンテンツの説明を提供する

問題 2

ほとんどの Android デバイスに組み込まれているユーザー補助ツールは次のうちどれですか。

▢ TalkBack

▢ ユーザー補助検証ツール

▢ Android Studio で、[Refactor] > [Add RTL support where possible]

▢ Lint

問題 3

チップの説明として正しくないものは、次のうちどれですか。

▢ チップを ChipGroup の一部として表示する。

ChipGroup の色状態リストを指定できます。

▢ チップは、入力、属性、アクションを表すコンパクトな要素です。

▢ アプリでチップを使用する場合は、常に DarkTheme を有効にする必要があります。

問題 4

ダークモードとライトモードのスタイルは、どのテーマで指定できますか。

DayNight

DarkTheme

DarkAndLightTheme

Light

問題 5

ライブ リージョンとは何ですか?

▢ ユーザーにとって重要な情報を含むノード

▢ マテリアル ガイドラインに沿って形状が変わる画面領域

▢ 動画のストリーミングが可能なビュー

▢ アニメーション化したドローアブル