How to set my own Menu and Back icons for Toolbar?
Asked Answered
H

1

1

I use Navigation Component which automatically handles if app should display Menu button to display to open navigation drawer or Back button to return back to home (dashboard for example):

    setupActionBarWithNavController(navController, appBarConfiguration)
    binding.navigationDrawer.setupWithNavController(navController)
    binding.bottomNavigationView.setupWithNavController(navController)

and navController.addOnDestinationChangedListener { _, destination, bundle -> ... }

So it can be

enter image description here

or

enter image description here

Navigation Component automatically sets those icons.

How can I override each icon? I need to override Menu and Back buttons icon.

Please don't mention methods which only set one icon...

Hogan answered 2/11, 2021 at 14:47 Comment(2)
Do you want to change the icon type i.e. the burger/back arrow?Uboat
@Uboat yes, but not in addOnDestinationChangedListenerHogan
U
2

Navigation Component automatically sets those icons.

How can I override each icon? I need to override Menu and Back buttons icon.

So, now you can navigate between the fragments, upon that you removed the fragment that you want to show the back/up button from the top hierarchy of the AppBarConfiguration.

Assuming you've 3 fragments: home, gallery, and slideshow; and you wish to show the back button on the gallery fragment, and the normal menu button in others.

So, you'd have something like:

val appBarConfiguration = AppBarConfiguration(
    setOf(
        R.id.nav_home, R.id.nav_slideshow
    ), drawerLayout
)

setupActionBarWithNavController(navController, appBarConfiguration)

Now we need to change the icons without using addOnDestinationChangedListener.

The icon can be changed with supportActionBar.setHomeAsUpIndicator(drawableRes)

But, actually icons need to be changed manually as this is not the default behavior of the drawer layout, and navigation components has no idea about that; so you can do that using the APIs of the drawer layout.

So, first register a listener to this icon with binding.drawerLayout.addDrawerListener(toggle) and this requires to create the ActionBarDrawerToggle, so save it locally in the activity, and the rest is in the code comments:

class MainActivity : AppCompatActivity() {

    private var toggle: ActionBarDrawerToggle? = null

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

        // Intialization code is omitted....
        
        toggle = getActionBarDrawerToggle(binding.drawerLayout, binding.appBarMain.toolbar).apply {
            setToolbarNavigationClickListener {
                // Back to home fragment for any hit to the back button
                navController.navigate(R.id.nav_home)
            }
            // Intialize the icon at the app start
            enableHomeBackIcon(false)
        }
    }

    fun enableHomeBackIcon(enabled: Boolean) {
        // Enable/Disable opening the drawer from the start side
        toggle?.isDrawerIndicatorEnabled = !enabled
       
        // Change the default burger icon
        supportActionBar?.setHomeAsUpIndicator(
            if (enabled) R.drawable.back_arrow
            else R.drawable.burger
        )
    }

    private fun getActionBarDrawerToggle(
        drawerLayout: DrawerLayout,
        toolbar: Toolbar
    ): ActionBarDrawerToggle {
        toggle = ActionBarDrawerToggle(
            this,
            drawerLayout,
            toolbar,
            R.string.open,
            R.string.close
        )
        drawerLayout.addDrawerListener(toggle!!)
        toggle?.syncState()
        return toggle as ActionBarDrawerToggle
    }

}

And as per your requirement, instead of using addOnDestinationChangedListener, you can utilize the drawer fragments lifecycle method; I will be using onViewCreated():

Home & Slideshow fragment: Disable the back button through the activity:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    (requireActivity() as MainActivity).enableHomeBackIcon(false)
}

Gallery fragment: Enable the back button through the activity:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    (requireActivity() as MainActivity).enableHomeBackIcon(true)
}
Uboat answered 2/11, 2021 at 19:56 Comment(1)
I have the pretty much the same situation but i have only bottomNavigation without drawer and i can't set AppBar back icon. I've tried via supportActionBar?.setHomeAsUpIndicator but icon is not setted. How i can set back icon in this situation?Inexpugnable

© 2022 - 2024 — McMap. All rights reserved.