Vin Norman
Vin Norman

Reputation: 3312

How to handle nested BottomNavigationView with Android Navigation Component?

I'm working with with the Android Navigation Component (currently v2.1.0) and I'm trying to work out how best to handle a child screen needing its own BottomNavigationView, with the MainActivity already having a top level BottomNavigationView.

Google seem to really advocate for the Single Activity architecture for most cases. Here's how I presently have it:

 - Main Activity
   - NavHostFragment & Top Level BottomNav 
     NavHost has navGraph of main_navigation.xml: this has the MainActivity top level 
     bottom navigation fragments, (e.g. Groups, Courses, Profile etc.) and also a link to the child 
     fragment which should have its own BottomNav    
       - ChildFragment
         - Has its own NavHostFragment in its layout, and its own BottomNav
         This NavHost has navGraph of childfragment_navigation.xml: which, similar to MainActivity,
         handles the bottom navigation fragments for the child fragment etc. etc.

This has presented a few problems. First of all, I'm having to show & hide the MainActivity BottomNavigationView if the user navigates into this child fragment, as follows:

    private fun setupNavController() {
        val navController = findNavController(R.id.nav_host_fragment)
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_groups, R.id.navigation_courses, R.id.navigation_profile
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        nav_view.setupWithNavController(navController)
        navController.addOnDestinationChangedListener { _, destination, _ ->
            when (destination.id) {
                R.id.navigation_groups, R.id.navigation_courses, R.id.navigation_profile -> showBottomNavigation()
                else -> hideBottomNavigation()
            }
        }
    }

    override fun onSupportNavigateUp(): Boolean {
        return findNavController(R.id.nav_host_fragment).navigateUp() || super.onSupportNavigateUp()
    }

    private fun hideBottomNavigation() {
        nav_view.visibility = View.GONE
    }

    private fun showBottomNavigation() {
        nav_view.visibility = View.VISIBLE
    }

This feels really clunky, and a bit of a hack, and also starts to add some unwanted view logic into MainActivity.

The second issue is to do with the appbar and backstack stuff. Once I'm in the child fragment, I get the updated toolbar title for that child fragment, but then any further action bar updates don't work intially, and if I drill down into further child fragments, pressing back won't initially work other than taking me back to MainActivity. Adding app:defaultNavHost="true" to both NavHostFragments seemed to solve some bits, namely the back button working properly once in the Child Fragment, although the app bar up button doesn't work for child fragments of the child fragment, it always goes back to MainActivity.

I tried putting this in the Child Fragment:

NavigationUI.setupActionBarWithNavController(activity as AppCompatActivity, navController)

This updates the toolbar title, but the up button still goes back to Main Activity.

There's 3 possible solutions I can think of to this structure of app (with child fragments having their own bottom nav):

  1. Give up on Single Activity architecture, and have the Child Fragment actually be its own Activity
  2. Just use one nav_graph, one NavHostFragment and one BottomNav, and figure out a way to swap out the BottomNavigation menu once in the child - any guidance on that would be appreciated
  3. Persist with this child fragment having its own NavHostFragment and BottomNav, and figure out a way to handle the back stack, the app bar, and the showing/hiding of the bottom navs

Upvotes: 4

Views: 3218

Answers (1)

GeekSubhankar_
GeekSubhankar_

Reputation: 39

You can follow Google single Activity architecture pattern but single navHostFragment and single navGraph can't save you, You need to use multiple navHost each has it's own navGraph so, each has it's own navigation. You need to switch between multiple navHostFragment and each has it's own navigation so it will work accourdingly.

You can take help from this [https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt.]

Upvotes: 2

Related Questions