メニューの状態更新の流れ

流れは以下の通り。

  1. メニューの作成時に状態を設定する
  2. メニューを更新したいタイミングでメニューをActivity#invalidateOptionsMenu()を呼んでinvalidateする

メニューをinvalidateすれば1.の処理が再度走るので、1.で設定したい状態にする。

メニューのオブジェクトにアクセスできるのは基本的に onCreateOptionsMenuonOptionsItemSelectedコールバックからのみなので、 任意のタイミングでメニューオブジェクトを取得できない。

そのため代わりにActivity#invalidateOptionsMenu()メソッドを呼んで表示しなおす。

実装

メニューの作成(onCreateOptionsMenuコールバックの場合)

onCreateOptionsMenuを呼び出して表示・再表示時点で表示したい状態にする。

例えば以下はenable/disableを制御している。

override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
    super.onCreateOptionsMenu(menu, inflater)
    inflater.inflate(R.menu.menu_foo, menu)

    // invalidate された時点で表示したい状態に設定する
    menu.findItem(R.id.menu_some_action).isEnabled = trueかfalse
}

メニューの作成(MenuProviderの場合)

onCreateOptionsMenu/onOptionsItemSelectedコールバックを使う方式はdeprecatedとなった。 代わりにMenuProviderを登録する方式となり、このMenuProvideronCreateMenuonCreateOptionsMenuと同等なのでonCreateOptionsMenuを実装すればオーケー。

参考: 【Android,Kotlin】メニューの処理をMenuProviderにする

activity?.addMenuProvider(
    object : MenuProvider {
        override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
          inflater.inflate(R.menu.menu_foo, menu)

          // invalidate された時点で表示したい状態に設定する
          menu.findItem(R.id.menu_some_action).isEnabled = trueかfalse
        }

        override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
          // ...
        }
    },
    viewLifecycleOwner,
    Lifecycle.State.RESUMED
)

メニューのinvalidate

更新したいタイミングでActivityinvalidateOptionsMenuメソッドを呼び出す。

activity?.invalidateOptionsMenu()