Search code examples
androidnavigation-drawerandroid-architecture-components

How do I modify the Toolbar/ActionBar when using the Navigation Component with a DrawerLayout?


I've followed the Developer Guide and added a DrawerLayout to my single-Activity app. My activity layout looks like this:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <fragment
            android:id="@+id/navHostFragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"/>
    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navigation"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav"
        app:headerLayout="@layout/nav_view_header"
        app:itemTextColor="@color/lightGrey"/>

</androidx.drawerlayout.widget.DrawerLayout>

And my Activity code like this:

class MainActivity : AppCompatActivity() {

    private val logTag = MainActivity::class.java.name

    private lateinit var appBarConfiguration : AppBarConfiguration

    private var model: Model? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        val navController = findNavController(R.id.navHostFragment)

        appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

        setupActionBarWithNavController(navController, appBarConfiguration)
        navigation.setupWithNavController(navController)

        navigation.menu.getItem(0).icon = getDrawable(R.drawable.ic_completed)
        navigation.menu.getItem(1).icon = getDrawable(R.drawable.ic_remaining)

        val viewModel: CommandViewModel by viewModels()
        viewModel.command.observe(this,  Observer<Command>{command ->
            model = getModel(this)
            val navHeaderView = navigation.getHeaderView(0)
            val completion  = navHeaderView.findViewById<TextView>(R.id.completion)
            completion.text = model?.completionMessage(this)
        })
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return item.onNavDestinationSelected(findNavController(R.id.navHostFragment))
                || super.onOptionsItemSelected(item)
    }

    override fun onSupportNavigateUp(): Boolean {
        return findNavController(R.id.navHostFragment).navigateUp(appBarConfiguration)
    }

}

Note that there's no Toolbar instance in the layout. The Navigation component is creating one for me. If I add one to the layout, I get another one on the screen right under the first one.

Now I'd like to add a button (a ToggleButton actually) to the right hand side of the Toolbar. How do I do this when I have no layout XML for the Toolbar? I'd prefer to do this in XML rather than Java/Kotlin, if it's all the same.

Note that implementing onCreateOptionsMenu() in the Activity and inflating the menu there does nothing.


Solution

  • The material design guidelines for the navigation drawer denote that the drawer should go over the app bar. This is not possible when using the default action bar as that action bar is always above any content you provide.

    Instead, you must add a Toolbar to your layout and use a NoActionBar theme for your activity (which removes the default action bar) - just make sure to call setSupportActionBar(toolbar) before the call to setupActionBarWithNavController() to use your Toolbar as the action bar.

    Once you have your own Toolbar in your layout, you can add views to it directly.