LoginSignup
2
0

ActionBarをMenuHostHelperに対応させる

私の過去記事でActcionBarのサンプルを投稿しましたが、Activityにか対応していませんでした。
ActionBarをカスタマイズしてみる

Fragmentに対応させるのと当時に、ActcionBarの制御方法がMenuHostHelperに変わっているので、その対応も同時に紹介します。

MenuHostHelperについては公式でもあまり詳しく説明されておらず、androidx.activity:activity:1.4.0-alpha01の変更点として説明されています。

そして、今は公式ではActionBarよりもToolBarを使用することを推奨していて、説明もToolbarに変わっています。ToolBarの説明は別途として、今回は従来通りのActionBarをMenuHostHelperに対応させる説明をします。

MainActivity

メニューの定義ファイルの作り方は前回と同じです。MainActivity.kt側の対応は、以下の様になります。わかりやすいように関数を分けました。

MainActivity.kt
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater) .apply {
            setContentView(this.root)
        }
        supportActionBar?.setTitle("あー、ほげほげ")
        supportActionBar?.setBackgroundDrawable(ColorDrawable(Color.GREEN))
        setupMenuBar()
    }

    private fun setupMenuBar() {
            addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                menuInflater.inflate(R.menu.menu_sample, menu)
            }

            override fun onMenuItemSelected(item: MenuItem): Boolean {
                when (item.itemId) {
                    R.id.iconItem1 ->  ・・・                    
                    else -> {}
                }
                return true
            }
        })
    }
}

ミソは

addMenuProvider(object : MenuProvider { ・・・

でこのaddMenuProviderはComponentActivityの中で、MenuHostHelper#addMenuProviderを呼び出しています。

関数、onCreateMenuinflateして、onMenuItemSelectedでActionBarのアイコン、またはメニューがタップされた場合の処理を書きます。

Fragment側の対応

おそらく、Activity1個に対し複数Fragmnent方式でくるくる画面を入れ替えて遷移するような方式だとActionBarは全てのFragmnentで共有したくなると思います。一部、特定のFragmentによってはActionBarの特定のアイコン、メニューを非表示にしたくなると思います。(タップさせない)

その場合、最大公約数的に、メニュー定義ファイルは1個で全てを記述し、MainActivityに処理を集約します。各Fragmentは違うところだけ書きます。

Fragment1.kt
class Fragment1 : Fragment() {
    private lateinit var binding: Fragment1Binding
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
    ): View {
        binding = Fragment1Binding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupMenuBar()
        ・・・
    }

    private fun setupMenuBar() {
         val menuHost: MenuHost = requireActivity()
         menuHost.addMenuProvider(object : MenuProvider {
            override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
                // 空
            }

             override fun onPrepareMenu(menu: Menu) {
                 menu.findItem(R.id.iconItem1).isVisible = false // アイコン
                 menu.findItem(R.id.menu_item3_1).isVisible = false // メニュー
             }

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

わかりやすいように関数を分けました。Activityの場合とちょっと違います。

val menuHost: MenuHost = requireActivity()

MenuHostはActivityのMenuHostを取得しています。addMenuProviderはActivityと引数が違います。LifecycleOwnerと、Lifecycle.Stateが必要です。

fun addMenuProvider(
    provider: MenuProvider,
    owner: LifecycleOwner,
    state: Lifecycle.State
): Unit

onCreateMenu関数は空です。Activityではここでメニュー定義ファイルをinflateしていましたが、FragmentでもinflateするとActionBarのアイコン、メニューが2倍になります。

onMenuItemSelected関数も空でtrueだけ返せばいいです。ActionBarのアイコン、メニューがタップされた場合のハンドリングは全てMainActivityでやります。

あと、MainActivityになかったのが、onPrepareMenu関数。
ここではこのFragmentに特化して表示したくない、ActionBarのアイコン、メニューがある場合、そのisVisible を false にします。

Fragmentが他に複数ある場合も同様です。

最後に

ソースはgitHubにpushしました。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0