Navigation+ToolbarでOptionsMenuを出すにはsetSupportActionBarの位置に気をつける


概要

JetpackのNavigationの話です。
https://developer.android.com/guide/navigation

タイトルどおりですが、NavigationでToolbarを使ってOptionsMenuを出すときにちょっとしたことでつまずいたので残しておきます。

Navigationのバージョンは以下です。

implementation 'androidx.navigation:navigation-fragment-ktx:2.1.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.1.0'

構成

MainActivityにToolbarがあります。

表示する画面はFragmentで作っており、2つの画面があります。
1つめのFragmentのToolbarには、タイトルだけ表示されています。
2つめのFragmentのToolbarには、1つめのFragmentに戻るnavigationIconとOptionsMenuがあります。

ToolbarのセットアップはActivityで、OptionsMenuのセットアップは2つめのFragmentで行っています。


Toolbarのセットアップ

MainActivity.kt

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
        setupToolbar()
    }

    private fun setupToolbar() {
        val navController = findNavController(R.id.nav_host_fragment)
        val toolbar = binding.toolbar

        // (1) OptionsMenuを出すために必要
        setSupportActionBar(toolbar)
        // (2) タイトル設定、Up navigateボタンのために必要
        toolbar.setupWithNavController(navController)
        // (2)はこちらの書き方でもOK
        // NavigationUI.setupWithNavController(toolbar, navController)
    }
}

上記のようにActivityでToolbarの設定を行うと、期待通りの挙動になります。

OptionsMenuが出ない


private fun setupToolbar() {
        val navController = findNavController(R.id.nav_host_fragment)
        val toolbar = binding.toolbar

        // (2) タイトル設定、Up navigateボタンのために必要
        toolbar.setupWithNavController(navController)
        // (2)はこちらの書き方でもOK
        // NavigationUI.setupWithNavController(toolbar, navController)
    }

setSupportActionBar(toolbar)を呼ばないと、OptionsMenuが出ません。

Up navigateボタンが効かない


private fun setupToolbar() {
        val navController = findNavController(R.id.nav_host_fragment)
        val toolbar = binding.toolbar

        // (2) タイトル設定、Up navigateボタンのために必要
        toolbar.setupWithNavController(navController)
        // (2)はこちらの書き方でもOK
        // NavigationUI.setupWithNavController(toolbar, navController)

        // (1) OptionsMenuを出すために必要
        setSupportActionBar(toolbar)
    }

このように、setupWithNavControllerの後に、setSupportActionBar(toolbar)してしまうと、Upボタンは表示されているのに効きません。

なお、Toolbarを使用する場合は、Navigationがナビゲーションボタンのイベントを自動で処理してくれるため、onSupportNavigateUp()をオーバーライドする必要はありません。

サンプルコード

下記にコードがあります。
https://github.com/iiinaiii/UI-Samples/blob/master/app/src/main/java/com/iiinaiii/uisamples/ui/MainActivity.kt