Mokelab Blog

#54 AndroidでToDoアプリを作る - 作成画面への遷移

今回はアプリのメイン画面からToDo作成画面に遷移するところまでを実装します。

フローティングアクションボタンの配置

まず、メイン画面からToDo作成画面への遷移を作ります。メイン画面において、ToDo作成はメインの操作といえます。 メインの操作は画面右下にフローティングアクションボタン(以下、FABと表記)として配置するのがよいでしょう。

FABには追加アイコンを設定する必要があります。グラフィックデザイナーさんにわざわざアイコンを描いてもらうのは申し訳ないので、ベクター画像をアプリに追加します。appフォルダの上で右クリック→「New」→「Vector Assets」を選びます。

Asset Studioのダイアログが表示されるので、Clip Artの部分のドロイド君のアイコンをクリックします。

すると、アイコンの一覧が表示されます。ここで表示されるアイコンはmaterial.ioのアイコンで提供されているものです。今回は追加アイコンをアプリに入れたいので、「Add」と検索し、Addアイコンを探します。

アイコンを選んだら、右下の「Next」をクリックします。

どのフォルダにベクター画像をいれるか選ぶ画面になります。そのまま右下の「Finish」をクリックします。これでアプリに追加アイコンを加えることができました。

次にメイン画面にFABを追加します。activity_main.xmlを開くとこの回で追加したボタンが配置されているので、削除します。

左上のPaletteのところで「fab」と検索し、Floating Action Buttonを探します。

FABをレイアウトに追加しようとすると、アイコン選択のためのダイアログが表示されます。先ほどアプリに加えたAddアイコンを選びます。

配置したFABの位置が定まるよう、制約を加えます。右下に配置したいので、次の2つの制約を加えます。Android Studioが自動で割り振るIDが長いので、fabに変更しておきます。

これでメイン画面にToDo作成画面に遷移するためのFABを配置することができました。

View Bindingの追加

次はFABタップ時の処理の記述ですが、ここで今後の作業を楽にするため、アプリにビューバインディング(View Binding)を追加します。ViewBindingとはビューを操作するコードを簡単に記述できる機能です。公式ドキュメントはこちらです。似たような機能としてデータバインディング(Data Binding)がありますが、レイアウトXMLのルート要素を変更する必要があるなど、手間がかかるので今回はView Bindingを使います。

View Bindingをアプリに追加するには、app/build.gradleのandroidセクションに次の記述を追加します。

android {
  ...
  buildFeatures {
      viewBinding true
  }
}

古いGradleプラグインの場合は次の記述を使います(本記事執筆時、公式ドキュメントの日本語版はこちらでした。。。)

android {
  ...
  viewBinding {
      enabled = true
  }
}

記述を追加したら右上の「Sync now」を忘れずにクリックします。これでアプリにView Bindingが追加されました。

FABタップ時の処理を記述する

最後にFABタップ時の処理を記述します。先ほどView Bindingを追加したので、MainFragmentで早速使ってみます。

@AndroidEntryPoint
class MainFragment: Fragment(R.layout.main_fragment) {
  private val vm: MainViewModel by viewModels()

  // ここから下を追加
  private var _binding: MainFragmentBinding? = null
  private val binding: MainFragmentBinding get() = _binding!!
  
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    this._binding = MainFragmentBinding.bind(view)
  }
  
  override fun onDestroyView() {
    super.onDestroyView()
    this._binding = null
  }
}

View Bindingを追加すると、自動で「レイアウトXMLのファイル名+Binding」というクラスが生成されます(ファイル名をfragment_main.xmlにしなかったのはこのためです)。 lateinit varにしたいところですが、onDestroyViewのタイミングでnullをセットし破棄したいので、nullableなvarとしてもたせます。 そしてビューが生存している範囲ではnon-nullであることが保障できるので、bindingプロパティも作ります。なお、この方法はGoogleが出しているサンプルで採用されています。

View Bindingのセットができたので、onViewCreatedでFABタップ時の処理を記述します。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  super.onViewCreated(view, savedInstanceState)
  this._binding = MainFragmentBinding.bind(view)
  
  binding.fab.setOnClickListener { 
    findNavController().navigate(R.id.action_mainFragment_to_createToDoFragment)
  }
}

Bindingの中には、ビューのIDに対しfindViewById()した結果が自動で入っています。FABタップ時の処理は通常のボタンと同様にsetOnClickListenerで記述します。

Navigationを使った画面遷移は、findNavController()NavControllerを取得し、navigate()を呼ぶだけです。引数には画面遷移を作る回で追加したアクションのIDを指定します。なお、findNavController()はandroidx.navigation:navigation-fragment-ktxで定義されている拡張関数です。

ここまで実装したら動作確認をしてみましょう。右下のFABをタップするとToDo作成画面に遷移し、バックボタンでメイン画面に戻ることができればOKです。

まとめ

メイン画面にFABを追加し、タップするとToDo作成画面に遷移するところまでを実装してみました。ベクター画像の追加やView Bindingの導入などは今後も使えるテクニックなので、使えるようになっておきましょう。

本サイトではサービス向上のため、Google Analyticsを導入しています。分析にはCookieを利用しています。