#38 2020年版、Androidでバックボタンを押したときの動作を変える方法
Androidで、バックボタンを押した時(戻るジェスチャーをした時)は、1つ前のフラグメントや アクティビティに戻ります。今回はその処理を変更する方法を紹介します。
今までの方法
バックボタンを押した時はActivity
のonBackPressed()
が呼ばれます。今まではこのメソッドをオーバーライドし、バックボタンの処理を行いたいフラグメントなどに
イベントをなんとかして通知する方法を各自作っていました。
2020年7月時点での方法
FragmentActivity
やAppCompatActivity
に、
OnBackPressedDispatcher
が追加されました。このオブジェクトに対し、コールバックを渡すことで
バックボタンを押したときの処理を変更することができます。
フラグメントで使用する例です。トーストを表示しつつ、1つ前の画面に戻ります。
class MainFragment : Fragment(R.layout.fragment_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requireActivity().onBackPressedDispatcher.addCallback(this) {
Toast.makeText(
requireContext(),
"Back pressed",
Toast.LENGTH_LONG
).show()
findNavController().popBackStack()
}
}
}
addCallback(this, {})
はactivity-ktx
の拡張関数なので注意しましょう(Android
Studioの候補に出てこなくて焦りました)。
第1引数でLifecycleOwner
を渡すことで、コールバックを有効にするタイミングと、removeするタイミングを制御しています。
Navigation UIとセットで使う場合
NavigationUIを使うと、ナビゲーションの状態とアクションバー/ツールバーの状態をあわせることができます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
// FragmentContainerViewを使ってる場合は
// ここに書かないとNavControllerが見つからない。。。
NavigationUI.setupActionBarWithNavController(
this, findNavController(R.id.fragment))
}
}
このようにアクションバーとセットで使う場合、onSupportNavigateUp()
を実装する必要があります。
NavigationUIが登場した時のサンプルだと、次のように実装していたと思います。
override fun onSupportNavigateUp()
= findNavController(R.id.fragment).navigateUp()
しかし、いきなりnavigateUp()
を呼ぶと、アクションバーにある戻るボタン(←)タップ時、セットしたコールバックを無視して戻る処理が行われます。
フラグメント側でセットしたコールバックが呼ばれるようにするには、次のようにします。
override fun onSupportNavigateUp(): Boolean {
if (onBackPressedDispatcher.hasEnabledCallbacks()) {
onBackPressedDispatcher.onBackPressed()
}
return true
}
これで、アクションバーにある戻るボタンタップ時もコールバックが呼ばれるようになります。
まとめ
onBackPressedDispatcher
を使ったバック時の処理の書き方を説明しました。
戻る前に保存するかどうかを聞くことは多いと思うので、使ってみましょう。
コラム:「アプリを終了しますか?」
今回紹介した方法を使うと、ルートとなるフラグメントで「アプリを終了しますか?」と確認することもできてしまいます。 ユーザーは「アプリを終了させたい」からバックボタンを押しているのに、そこで確認が入ることは操作性を著しく低下させてしまいます。 Androidに標準で入っているアプリのほぼすべてで、「アプリを終了しますか?」の確認を行っていない動作にあわせ、操作性を低下させないようにしましょう。
例外はゲーム系アプリといった「アプリの起動にとても時間のかかるもの」でしょうか。。。