Search code examples
androidkotlinandroid-architecture-componentsandroid-architecture-navigation

BottomAppBar with BottomNavigationDrawer connected to NavigationController


Hi I'm trying to use new arch components in my project. Short description what I want to achieve:

  • When user is on MainFragment I want to display navigation icon (Hamburger) on BottomAppBar. User is able to click navigation icon and display BottomNavigationDrawer
  • When user select some menu item, or click something on MainFragment he is moved to another fragment, let say DebtDetailsFragment. Then Hamburger should be replaced with 'Back arrow' by NavigationController

Below I pasted my MainActivity code. When I comment line with navigation controller, the Hamburger icon is visible and BottomNavigationDrawer is able to display.

But when I uncomment this line, the Hamburger disappear because NavigationController knows nothing about NavigationView used in BottomNavigationDrawer. I don't use DrawerLayout, so controller thinks Hamburger is not needed.

Method setupWithNavController can control Hamburger icon and back arrow, but I have to provide DrawerLayout as parameter which I don't use.

Documentation for this method:

The Toolbar will also display the Up button when you are on a non-root destination and the drawer icon when on the root destination, automatically animating between them. This method will call [DrawerLayout.navigateUp] when the navigation icon is clicked.

So the question is, how to display Hamburger icon when NavigationController is connected with BottomAppBar but without DrawerLayout? I will handle hamburger click myself in onOptionsItemSelected method.


class MainActivity : BaseActivity() {

    @Inject
    lateinit var viewModelProvider: ViewModelProvider.Factory

    private val viewModel: MainActivityViewModel by lazy {
        ViewModelProviders.of(this, viewModelProvider).get(MainActivityViewModel::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(bottomAppBar)
        val navController = findNavController(R.id.main_nav_host_fragment)
        //bottomAppBar.setupWithNavController(navController)
        
        onDestroyDisposables += viewModel.uiStateObservable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(::render, Timber::e)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.bottomappbar_menu, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        when (item?.itemId) {
            android.R.id.home -> {
                val bottomNavDrawerFragment = BottomNavigationDrawerFragment()
                bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag)
            }
        }
        return super.onOptionsItemSelected(item)
    }

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

Without setted Navigation controller:

Without setted Navigation controller

BottomNavigationDrawer

BottomNavigationDrawer

With setted NavigationController - Hamburger invisible.

With NavigationController


Solution

  • The BottomAppBar should never display an Up button as per the anatomy of the BottomAppBar - it should only ever display the drawer icon. As seen in the behavior documentation, the Up button should be displayed in a top Toolbar.

    Therefore, you should never be calling bottomAppBar.setupWithNavController(navController), but instead calling setupWithNavController(navController) using whatever top Toolbar you have.

    To set up your BottomAppBar, you should instead set your own drawer icon and handle clicks on the drawer icon yourself.

    The DrawerArrowDrawable class is available to give you a correct drawer icon:

    val icon = DrawerArrowDrawable(bottomAppBar.context)
    bottomAppBar.navigationIcon = icon