〈kotlin〉MenuHost, MenuProviderでアプリバーにメニュー表示

Android studioでkotlinを使ってAndroidアプリ作成の勉強中。

ホストアクティビティでアプリバーを持ち、
フラグメントでアプリバーにメニューを表示させたい。
この時に使うsetHasOptionMenu(true)が非推奨になっていたので他の方法を調べた。

これまでの方法

setHasOptionMenu(true)を記述することで、
フラグメントがメニュー関連のコールバックを受け取ることをシステムに伝える。

class ExampleFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        inflater.inflate(R.menu.sample_menu, menu)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return when (item.itemId) {
            ...
        }
    }
}

アクティビティを取得し、MenuProviderインスタンスを追加することで、
メニュー項目をアプリバーに追加できる。

class ExampleFragment : Fragment(R.layout.fragment_example) {

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

    val menuHost: MenuHost = requireActivity()

    menuHost.addMenuProvider(object : MenuProvider {
      override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
        menuInflater.inflate(R.menu.example_menu, menu)
      }

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

addMenuProviderの引数は

  • provider: MenuProvider(メニューリソースと選択時の処理を指定する)
  • owner: LifecycleOwner
  • state: Lifecycle.State

LifecycleOwnerがLifecycle.Stateに達したらMenuProviderを追加する。
lifecycleを追加しておくことで、lifecycleの状態に応じてメニュー項目が自動で制御され、
指定したlifecycleの破棄されるときにMenuProviderも削除される。

参考
android - 'setHasOptionsMenu(Boolean): Unit' is deprecated. Deprecated in Java - Stack Overflow
Activity  |  Android デベロッパー  |  Android Developers
MenuHostHelper  |  Android Developers