アクティビティとインテント

1. はじめに

ここまで使用したアプリには、アクティビティが 1 つしかありませんでした。実際には、多くの Android アプリに複数のアクティビティと、それらのアクティビティ間のナビゲーションが必要です。

この Codelab では、複数のアクティビティを使用し、インテントを使用してそれらのアクティビティ間を移動し、他のアプリにデータを引き渡す辞書アプリを作成します。

前提条件

次のことを行える必要があります。

  • Android Studio でプロジェクトを操作する。
  • Android Studio で XML リソースを使用および追加する。
  • 既存のクラスのメソッドをオーバーライドして実装する。
  • Kotlin クラスのインスタンスを作成し、クラス プロパティにアクセスして、メソッドを呼び出す。
  • developer.android.com のドキュメントを参照して、特定のクラスの詳細を確認する。

学習内容

次のことを行う方法を学習します。

  • 明示的インテントを使用して、特定のアクティビティに移動する。
  • 暗黙的インテントを使用して、別のアプリのコンテンツに移動する。
  • アプリバーにボタンを追加するメニュー オプションを追加する。

作成するアプリの概要

  • インテントを使用し、オプション メニューを追加することで、辞書アプリに画面間のナビゲーションを実装します。

必要なもの

  • Android Studio がインストールされているパソコン

2. スターター コード

次のステップでは、Words アプリを使用します。Words アプリは、文字のリスト、各文字から始まる単語、ブラウザで各単語の定義を検索する機能を備えた、シンプルな辞書アプリです。

さらに多くの機能を組み込むこともできますが、インテントについて学習することが目的なので、アプリ全体をビルドする必要はありません。ここでは代わりに、未完成のプロジェクト(スターター プロジェクト)が用意されています。

このプロジェクトにはすべての画面が実装されていますが、ある画面から別の画面に移動することはできません。この Codelab の課題は、すべてをゼロから構築することなく、インテントを使用してプロジェクト全体を機能させることです。

この Codelab のスターター コードをダウンロードする

この Codelab では、ここで学んだ機能を使って拡張するためのスターター コードが提供されます。スターター コードには、以前の Codelab で学んだコードが含まれている場合があります。学んでいないコードが含まれている可能性もありますが、これについては今後の Codelab で学習します。

GitHub からスターター コードをダウンロードする場合、フォルダ名が android-basics-kotlin-words-app-starter であることに注意してください。Android Studio でプロジェクトを開くときは、このフォルダを選択してください。

Git コマンドに習熟している場合、スターター コードは「starter」というブランチにあることに注意してください。このリポジトリのクローンを作成した後、origin/starter ブランチからコードをチェックアウトします。Git コマンドを初めて使用する場合は、次の手順に沿って GitHub からコードをダウンロードしてください。

  1. プロジェクト用に提供されている GitHub リポジトリ ページに移動します。
  2. ブランチ名が Codelab で指定されたブランチ名と一致していることを確認します。たとえば、次のスクリーンショットでは、ブランチ名は main です。

1e4c0d2c081a8fd2.png

  1. プロジェクトの GitHub ページで、[Code] ボタンをクリックすると、ポップアップが表示されます。

1debcf330fd04c7b.png

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

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

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

d8e9dbdeafe9038a.png

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

8d1fda7396afe8e5.png

  1. ファイル ブラウザで、展開したプロジェクト フォルダがある場所([ダウンロード] フォルダなど)に移動します。
  2. そのプロジェクト フォルダをダブルクリックします。
  3. Android Studio でプロジェクトが開かれるまで待ちます。
  4. 実行ボタン 8de56cba7583251f.png をクリックして、アプリをビルドし、実行します。期待どおりにビルドされることを確認します。

3. Words アプリの概要

次に進む前に、時間を設けプロジェクトの内容を把握してください。すべてのコンセプトを前のユニットで学んでいるはずです。現時点では、アプリは 2 つのアクティビティで構成され、それぞれがリサイクラー ビューとアダプターを備えています。

61af34429128695e.png

具体的には次のファイルを使用します。

  1. LetterAdapter は、MainActivityRecyclerView によって使用されます。各文字は onClickListener を使用したボタンで、現在は空になっています。このファイルで、DetailActivity に移動する際のボタンの押下を処理します。
  2. WordAdapter は、DetailActivityRecyclerView によって、単語のリストを表示するために使用されます。まだこの画面に移動することはできませんが、各単語には、onClickListener を使用した対応するボタンも用意されています。このファイルに、ブラウザに移動して単語の定義を表示するコードを追加します。
  3. MainActivity にもいくつかの変更が必要です。このファイルで、ユーザーがリストとグリッドのレイアウトを切り替えることができるようにするためのボタンを表示するオプション メニューを実装します。

ce3474dba2a9c1c8.png

プロジェクトについてここまで問題なく理解できたら、次のセクションに進み、インテントについて学びましょう。

4. インテントの概要

最初のプロジェクトを設定したので、次はインテントの概要と、アプリでインテントを使用する方法について説明します。

インテントとは、実行するアクションを表すオブジェクトです。インテントの最も一般的な用途は、アクティビティを起動することです(これ以外の目的でも使用されます)。インテントには、暗黙的インテントと明示的インテントの 2 種類があります。明示的インテントは非常に具体的であり、起動するアクティビティ(多くの場合はアプリ内の画面)を正確に把握できます。

これと比較して暗黙的インテントはやや抽象的です。リンクを開く、メールを作成する、電話をかけるといったアクションの種類をシステムに伝え、システムがリクエストの履行方法を決定します。今までそれとは知らずに、両方のタイプのインテントが動作しているのを見たことがあるはずです。一般に、自分のアプリ内でアクティビティを表示するときは、明示的インテントを使用します。

ただし、現在のアプリに関係しないアクション(Android の興味深いドキュメント ページを見つけ、友だちと共有したい場合など)には、暗黙的インテントを使用します。その場合、ページの共有に使用するアプリを確認するために、次のようなメニューを表示します。

e9c77033d9224170.png

明示的インテントはアプリ内でのアクションや画面の表示に使用し、そのプロセス全体に対して責任を持ちます。暗黙的インテントは一般に、他のアプリに関係するアクションの実行に使用され、その最終結果はシステムによって決まります。Words アプリでは、両方のタイプのインテントを使用します。

702236c6e2276f91.png

5. 明示的インテントを設定する

それでは、最初のインテントを実装しましょう。最初の画面でユーザーが文字をタップすると、単語のリストが表示された次の画面に移動するようにします。DetailActivity はすでに実装されているため、必要なのはこれをインテントで起動することだけです。アプリは起動するアクティビティを正確に把握しているため、明示的インテントを使用します。

インテントの作成と使用は、わずか数ステップで完了します。

  1. LetterAdapter.kt を開き、onBindViewHolder() まで下にスクロールします。ボタンのテキストを設定する行の下に、holder.buttononClickListener を設定します。
holder.button.setOnClickListener {

}
  1. 次に、context への参照を取得します。
val context = holder.itemView.context
  1. Intent を作成し、コンテキストと、デスティネーション アクティビティのクラス名を渡します。
val intent = Intent(context, DetailActivity::class.java)

表示するアクティビティの名前は DetailActivity::class.java で指定します。実際の DetailActivity オブジェクトはバックグラウンドで作成されます。

  1. putExtra メソッドを呼び出し、1 つ目の引数として「letter」を、2 つ目の引数としてボタンのテキストを渡します。
intent.putExtra("letter", holder.button.text.toString())

ここで、エクストラとは何かを考えてみましょう。インテントは一連の命令にすぎず、デスティネーション アクティビティのインスタンスはまだ存在しません。一方、エクストラとは、後で取得される名前が指定された、数値や文字列などのデータの一部です。これは、関数を呼び出すときに引数を渡すことに似ています。DetailActivity はどの文字に対しても表示できるため、表示する文字を指定する必要があります。

また、toString() の呼び出しが必要な理由も考えてみてください。ボタンのテキストは、すでに文字列ではないでしょうか?

確かに文字列の一種ですが、実際には CharSequence 型であり、インターフェースと呼ばれるものです。現時点では、これが型(String など)を確認し、特定の関数とプロパティを実装する方法であるということ以外は、Kotlin インターフェースについて知っておく必要はありません。CharSequence は、文字列に似たクラスの、より汎用的な表現と考えることができます。ボタンの text プロパティには文字列を指定することも、CharSequence であるオブジェクトを指定することもできます。ただし、putExtra() メソッドは CharSequence だけでなく String も受け入れるため、toString() を呼び出す必要があります。

  1. コンテキスト オブジェクトで startActivity() メソッドを呼び出し、intent を渡します。
context.startActivity(intent)

アプリを実行して文字をタップしてみましょう。詳細画面が表示されますが、タップした文字に関係なく、常に A の文字の単語が表示されます。intent エクストラとして渡される文字に対して適切な単語が表示されるように、詳細アクティビティで追加の作業を行う必要があります。

6. DetailActivity を設定する

最初の明示的インテントを作成できたので、続いて詳細画面に進みましょう。

DetailActivityonCreate メソッドで、setContentView の呼び出しの後にあるハードコードされた文字を、intent から渡された letterId を取得するコードに置き換えます。

val letterId = intent?.extras?.getString("letter").toString()

ここでは注目すべき点が多くあるため、1 つずつ見ていきましょう。

まず、intent プロパティはどこから来たのでしょうか。これは DetailActivity のプロパティではなく任意のアクティビティのプロパティで、アクティビティの起動に使用されるインテントへの参照を保持します。

extras プロパティは Bundle 型で、インテントに渡されたすべてのエクストラにアクセスする方法を提供します。

これらのプロパティは、どちらも疑問符でマークされています。その理由は、intent プロパティと extras プロパティは null 値許容で、値を持っても持たなくてもよいためです。場合によっては、変数を null にすることもできます。intent プロパティは、実際には Intent ではない場合があります(インテントからアクティビティが起動されていない場合)。また、extras プロパティが実際には Bundle ではなく、null という値である場合があります。Kotlin では、null は値がないことを意味します。オブジェクトは存在することもありますが、null の場合もあります。アプリが null オブジェクトのプロパティにアクセスしたり、そのオブジェクトで関数を呼び出したりしようとすると、アプリはクラッシュします。この値に安全にアクセスするには、名前の後に ? を配置します。これにより、intentnull の場合、アプリは extras プロパティへのアクセスを試みなくなります。また、extras が null の場合、コードは getString() を呼び出そうとしません。

null の安全性を確保するために疑問符が必要なプロパティは、型名の後に疑問符または感嘆符が付いているかどうかで判断できます。

b43155b06a5556e.png

最後に注意すべき点として、実際の文字は getString で取得されます。これは String? を返すため、その値が null ではなく String であることを確認するために toString() が呼び出されます。

アプリを実行して詳細画面に移動すると、各文字に対応する単語のリストが表示されます。

c465ef280fe3792a.png

クリーンアップ

インテントを実行するコードと、選択された文字を取得するコードの両方で、extra の名前が「letter」とハードコードされています。これはこの小さなアプリでは問題ありませんが、追跡するインテント エクストラが多い大きなアプリには適していません。

「letter」という定数を作成することも可能ですが、アプリにインテント エクストラを追加した場合に処理が難しくなります。また、この定数をどのクラスに配置するかも考える必要があります。この文字列は DetailActivityMainActivity の両方で使用されるため、コードを整理しつつ、複数のクラスで使用できる定数を定義する方法が必要です。

幸いなことに、Kotlin にはコンパニオン オブジェクトと呼ばれる、クラスの特定のインスタンスを使用せずに、定数を分離して使用できるようにする便利な機能が用意されています。コンパニオン オブジェクトは、クラスのインスタンスなどの他のオブジェクトに似ていますが、プログラムの実行中にコンパニオン オブジェクトのインスタンスは 1 つしか存在しません。そのため、シングルトン パターンと呼ばれることもあります。シングルトンのユースケースは他にも数多くありますが、この Codelab の範囲外となります。ここでは、定数を整理して DetailActivity の外部でアクセスできるようにするための方法として、コンパニオン オブジェクトを使用します。まず、コンパニオン オブジェクトを使用して、「letter」エクストラのコードをリファクタリングします。

  1. DetailActivityonCreate のすぐ上に次のコードを追加します。
companion object {

}

object キーワードを使用する以外は、クラスの定義と類似しています。キーワード companionDetailActivity クラスと関連付けられているため、別の型名を指定する必要はありません。

  1. 中かっこ内に letter 定数のプロパティを追加します。
const val LETTER = "letter"
  1. 新しい定数を使用するには、onCreate() でハードコードされた letter の呼び出しを次のように更新します。
val letterId = intent?.extras?.getString(LETTER).toString()

通常どおりドット表記で参照していますが、定数は DetailActivity に属します。

  1. LetterAdapter に切り替えて、新しい定数を使用するように putExtra の呼び出しを変更します。
intent.putExtra(DetailActivity.LETTER, holder.button.text.toString())

設定が完了しました。リファクタリングによりコードの読みやすさが向上し、メンテナンスも容易になりました。この定数や、他の追加した定数を変更する場合は、1 か所を変更するだけで済みます。

コンパニオン オブジェクトについて詳しくは、Kotlin ドキュメントのオブジェクトの式と宣言をご覧ください。

7. 暗黙的インテントを設定する

ほとんどの場合、デベロッパーはアプリ固有のアクティビティを表示しますが、どのアクティビティやアプリを起動すべきかわからない場合もあります。このアプリの詳細画面では、各単語が、単語の定義を表示するボタンになっています。

この例では、Google 検索が提供する辞書機能を使用します。ただし、アプリに新しいアクティビティを追加するのではなく、デバイスのブラウザを起動して検索ページを表示します。

この場合、Android のデフォルト ブラウザである Chrome でページを読み込むためのインテントが必要になるでしょうか?

そうとは限りません。

ユーザーがサードパーティのブラウザを好む場合もあります。または、スマートフォンにブラウザがプリインストールされている場合や、ユーザーが Google 検索アプリやサードパーティの辞書アプリをインストールしている場合もあります。

ユーザーがインストールしているアプリを正確に把握することはできず、ユーザーがどの方法で単語を検索したいかを推測することもできません。これは暗黙的インテントを使用する例として理想的です。アプリは必要なアクションに関する情報をシステムに提供します。システムはそのアクションの処理方法を判断し、必要に応じて追加情報をユーザーに求めます。

次の手順に沿って、暗黙的インテントを作成します。

  1. このアプリの場合は、Google で単語を検索します。最初の検索結果が、単語の定義として辞書に登録されます。すべての検索で同じベース URL が使用されるため、これを独自の定数として定義することをおすすめします。DetailActivity で、コンパニオン オブジェクトを変更して新しい定数 SEARCH_PREFIX を追加します。これは Google 検索のベース URL です。
companion object {
   const val LETTER = "letter"
   const val SEARCH_PREFIX = "https://www.google.com/search?q="
}
  1. 次に、WordAdapter を開き、onBindViewHolder() メソッドのボタンで setOnClickListener() を呼び出します。まず、検索クエリの Uri を作成します。parse() を呼び出して String から Uri を作成する場合、単語が SEARCH_PREFIX に追加されるように文字列形式を使用する必要があります。
holder.button.setOnClickListener {
    val queryUrl: Uri = Uri.parse("${DetailActivity.SEARCH_PREFIX}${item}")
}

URI はタイプミスではなく、Uniform Resource Identifier の略です。よく知られている URL(Uniform Resource Locator)は、ウェブページを指す文字列です。URI は、この形式のより一般的な用語です。すべての URL は URI ですが、すべての URI が URL であるとは限りません。たとえば、URI のひとつである電話番号のアドレスは tel: で始まっていますが、これは URL ではなく URN(Uniform Resource Name)と見なされます。両方を表現するために使用されるデータ型は URI と呼ばれます。

828cef3fdcfdaed.png

ここには、自分のアプリのアクティビティへの参照がないことに注意してください。最終的な用途は指示せずに URI を指定します。

  1. queryUrl を定義したら、新しい intent オブジェクトを初期化します。
val intent = Intent(Intent.ACTION_VIEW, queryUrl)

コンテキストとアクティビティを渡す代わりに、Intent.ACTION_VIEWURI と一緒に渡します。

ACTION_VIEW は、URI(この場合はウェブアドレス)を受け取る汎用インテントです。これにより、このインテントはユーザーのウェブブラウザで URI を開いて処理するということが、システムに伝わります。他にも次のようなインテント タイプがあります。

  • CATEGORY_APP_MAPS – マップアプリを起動する
  • CATEGORY_APP_EMAIL – メールアプリを起動する
  • CATEGORY_APP_GALLERY – ギャラリー(写真)アプリを起動する
  • ACTION_SET_ALARM – バックグラウンドでアラームを設定する
  • ACTION_DIAL – 通話を開始する

詳細については、よく使用されるインテントのドキュメントをご覧ください。

  1. 最後に、アプリ内で特定のアクティビティを起動していなくても、startActivity() を呼び出して intent を渡すことで、別のアプリを起動するようシステムに指示します。
context.startActivity(intent)

これで、アプリを起動して単語リストに移動し、いずれかの単語をタップすると、その URL に移動するようになりました(または、インストール済みのアプリに応じてオプションのリストが表示されます)。

コードを複雑化させることなく、ユーザーごとに動作を変えられるため、すべてのユーザーにシームレスなエクスペリエンスを提供できます。

8. メニューとアイコンを設定する

明示的インテントと暗黙的インテントを追加してアプリを完全に操作できるようになったので、次はメニュー オプションを追加します。これにより、ユーザーが文字のリスト レイアウトとグリッド レイアウトを切り替えられるようになります。

多くのアプリでは、画面の上部に次のようなバーが表示されます。これはアプリバーと呼ばれ、アプリ名を表示するだけでなくカスタマイズも可能で、有用なアクションのショートカットやオーバーフロー メニューなど、多くの便利な機能をホストできます。

dfc4095251c1466e.png

このアプリでは本格的なメニューは追加しませんが、カスタムボタンをアプリバーに追加して、ユーザーがレイアウトを変更できるようにする方法を説明します。

  1. まず、グリッドビューとリストビューを表す 2 つのアイコンをインポートする必要があります。「view module」(名前は ic_grid_layout とします)と「view list」(名前は ic_linear_layout とします)というクリップアートのベクター アセットを追加します。マテリアル アイコンの追加方法について詳しくは、こちらのページをご覧ください。

5a01fc03113ac399.png

  1. また、アプリバーに表示されるオプションや、使用するアイコンをシステムに知らせることも必要です。これを行うには、res フォルダを右クリックして、[New] > [Android Resource File] を選択して新しいリソース ファイルを追加します。[Resource Type] を Menu に、[File Name] を layout_menu に設定します。

c4f83806a1aa121b.png

  1. [OK] をクリックします。
  2. res/Menu/layout_menu を開きます。layout_menu.xml の内容を次のように置き換えます。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto">
   <item android:id="@+id/action_switch_layout"
       android:title="@string/action_switch_layout"
       android:icon="@drawable/ic_linear_layout"
       app:showAsAction="always" />
</menu>

メニュー ファイルの構造は非常にシンプルです。レイアウトが、個別のビューを保持するレイアウト マネージャーから始まるのと同様に、メニュー XML ファイルは、個々のオプションを含むメニュータグから始まります。

メニューには 1 つボタンと、以下のプロパティがあります。

  • id: ビューと同様にメニュー オプションにも ID があり、コード内で参照できます。
  • title: このテキストは今回のケースでは実際には表示されませんが、スクリーン リーダーがメニューを識別するのに役立ちます。
  • icon: デフォルトは ic_linear_layout です。ただし、ボタンが選択されると、グリッド アイコンの表示と非表示が切り替わります。
  • showAsAction: ボタンを表示する方法をシステムに指示します。「always」に設定されているため、このボタンは常にアプリバーに表示され、オーバーフロー メニューには含まれません。

もちろん、プロパティを設定しただけではメニューは機能しません。

メニューを機能させるには、MainActivity.kt にコードを追加する必要があります。

9. メニューボタンを実装する

メニューボタンを使用できるようにするために、MainActivity.kt に次のような変更を加えます。

  1. まず、アプリのレイアウト状態を追跡するためのプロパティを作成することをおすすめします。これにより、レイアウト ボタンを簡単に切り替えることができます。線形レイアウト マネージャーがデフォルトで使用されるように、デフォルト値を true に設定します。
private var isLinearLayoutManager = true
  1. ユーザーがボタンを切り替えると、項目のリストがグリッドに変わるようにします。リサイクラー ビューに関する Codelab で、レイアウト マネージャーが複数あることを説明しましたが、そのひとつである GridLayoutManager を使用すると、1 行に複数の項目を表示できます。
private fun chooseLayout() {
    if (isLinearLayoutManager) {
        recyclerView.layoutManager = LinearLayoutManager(this)
    } else {
        recyclerView.layoutManager = GridLayoutManager(this, 4)
    }
    recyclerView.adapter = LetterAdapter()
}

ここでは、if ステートメントを使用してレイアウト マネージャーを割り当てています。このコードでは layoutManager の設定だけでなく、アダプターの割り当ても行っています。LetterAdapter はリスト レイアウトとグリッド レイアウトの両方で使用されます。

  1. 最初に xml でメニューをセットアップしたときに、静的なアイコンを指定しました。しかし、レイアウトを切り替えた後は、新しい関数を反映するようにアイコンを更新する(リスト レイアウトに戻す)必要があります。ここでは、次回ボタンがタップされたときに切り替わるレイアウトに基づいて、線形レイアウトとグリッド レイアウトのアイコンを設定します。
private fun setIcon(menuItem: MenuItem?) {
   if (menuItem == null)
       return

   // Set the drawable for the menu icon based on which LayoutManager is currently in use

   // An if-clause can be used on the right side of an assignment if all paths return a value.
   // The following code is equivalent to
   // if (isLinearLayoutManager)
   //     menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
   // else menu.icon = ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
   menuItem.icon =
       if (isLinearLayoutManager)
           ContextCompat.getDrawable(this, R.drawable.ic_grid_layout)
       else ContextCompat.getDrawable(this, R.drawable.ic_linear_layout)
}

アイコンは、isLinearLayoutManager プロパティに基づいて条件付きで設定されます。

アプリで実際にメニューを使用するには、次の 2 つのメソッドもオーバーライドする必要があります。

  • onCreateOptionsMenu: オプション メニューをインフレートして、追加の設定を行います。
  • onOptionsItemSelected: ボタンが選択されたときに、実際に chooseLayout() を呼び出します。
  1. 次のように onCreateOptionsMenu をオーバーライドします。
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
   menuInflater.inflate(R.menu.layout_menu, menu)

   val layoutButton = menu?.findItem(R.id.action_switch_layout)
   // Calls code to set the icon based on the LinearLayoutManager of the RecyclerView
   setIcon(layoutButton)

   return true
}

ここでは、特に難しいことはありません。レイアウトをインフレートした後、レイアウトに基づいてアイコンが正しいことを確認する setIcon() を呼び出します。このメソッドは Boolean を返します。オプション メニューを作成する必要があるため、ここでは true を返します。

  1. 数行のコードを追加して、onOptionsItemSelected を次のように実装します。
override fun onOptionsItemSelected(item: MenuItem): Boolean {
   return when (item.itemId) {
       R.id.action_switch_layout -> {
           // Sets isLinearLayoutManager (a Boolean) to the opposite value
           isLinearLayoutManager = !isLinearLayoutManager
           // Sets layout and icon
           chooseLayout()
           setIcon(item)

           return true
       }
       //  Otherwise, do nothing and use the core event handling

       // when clauses require that all possible paths be accounted for explicitly,
       //  for instance both the true and false cases if the value is a Boolean,
       //  or an else to catch all unhandled cases.
       else -> super.onOptionsItemSelected(item)
   }
}

このメソッドはメニュー項目がタップされるたびに呼び出されるため、どのメニュー項目がタップされたのかを正確に確認する必要があります。上記のコードでは、when ステートメントを使用しています。idaction_switch_layout のメニュー項目と一致する場合は、isLinearLayoutManager の値を否定します。その後、chooseLayout()setIcon() を呼び出して UI を更新します。

アプリを実行する前に、もう 1 つ作業が残っています。レイアウト マネージャーとアダプターが chooseLayout() に設定されたため、新しいメソッドを呼び出すには、onCreate() 内の該当するコードを置き換える必要があります。変更後の onCreate() は以下のようになります。

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

   val binding = ActivityMainBinding.inflate(layoutInflater)
   setContentView(binding.root)

   recyclerView = binding.recyclerView
   // Sets the LinearLayoutManager of the recyclerview
   chooseLayout()
}

アプリを実行すると、メニューボタンでリストビューとグリッドビューを切り替えられるようになっています。

10. 解答コード

この Codelab のソリューション コードは、以下のプロジェクトにあります。

  1. プロジェクト用に提供されている GitHub リポジトリ ページに移動します。
  2. ブランチ名が Codelab で指定されたブランチ名と一致していることを確認します。たとえば、次のスクリーンショットでは、ブランチ名は main です。

1e4c0d2c081a8fd2.png

  1. プロジェクトの GitHub ページで、[Code] ボタンをクリックすると、ポップアップが表示されます。

1debcf330fd04c7b.png

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

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

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

d8e9dbdeafe9038a.png

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

8d1fda7396afe8e5.png

  1. ファイル ブラウザで、展開したプロジェクト フォルダがある場所([ダウンロード] フォルダなど)に移動します。
  2. そのプロジェクト フォルダをダブルクリックします。
  3. Android Studio でプロジェクトが開かれるまで待ちます。
  4. 実行ボタン 8de56cba7583251f.png をクリックして、アプリをビルドし、実行します。期待どおりにビルドされることを確認します。

11. 概要

  • 明示的インテントは、アプリ内の特定のアクティビティに移動するために使用します。
  • 暗黙的インテントは特定のアクション(リンクを開く、画像を共有するなど)に対応し、そのインテントを実現する方法はシステムが決定します。
  • メニュー オプションを使用すると、ボタンとメニューをアプリバーに追加できます。
  • コンパニオン オブジェクトは、型のインスタンスではなく、再利用可能な定数を型に関連付ける手段を提供します。

インテントを実行するには:

  • コンテキストへの参照を取得します。
  • 明示的か暗黙的かに応じて、アクティビティまたはインテント タイプを提供する Intent オブジェクトを作成します。
  • putExtra() を呼び出して必要なデータを渡します。
  • startActivity() を呼び出して、intent オブジェクトを渡します。

12. 詳細