Search code examples
androidandroidxandroid-jetpackandroid-jetpack-navigation

NavigationComponent navigate away from BottomNavitationView


I am using NavitationComponent and my start screen has a BottomNavigationView. This is declared in my activity's XML, something like this:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <FrameLayout
        android:id="@+id/bottomNavigationLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/nav_view"
            android:layout_width="match_parent"
            android:layout_height="105dp"
            android:layout_marginStart="0dp"
            android:layout_marginEnd="0dp"
            app:menu="@menu/bottom_nav_menu" />

    </FrameLayout>

    <!-- Screen contents -->
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@id/bottomNavigationLayout"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/home_navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

I want to navigate to a separate screen entirely, that does not feature the BottomNavigationView. However since it lives on the Activity it persists. What is the recommended approach in such case? I would like to avoid using startActivity, that just feels like defeating the purpose of having Navigation Component in the first place.


Solution

  • When using BottomNavigation with Android Navigation Component in an enterprise app we face multiple issues:

    1. Handling back stack in conjunction with BottomNavigation that has a workaround inside Google Samples.
    2. Using a shared Toolbar with a dynamic menu updates
    3. Android BottomNavigation hide/show in different fragments

    We ended up with this solution:

    In our Activity we set a listener for the navigation component:

    findNavController().addOnDestinationChangedListener(this)
    
    override fun onDestinationChanged(controller: NavController, destination: NavDestination, arguments: Bundle?) {
            //Check Destination
    }
    

    We defined UI configs (Toolbar & BottomNavigation) for each fragment:

    data class UiConfig(val toolbarConfig: ToolbarConfig, val bottomNavigationConfig: BottomNavigationConfig)
    
    data class ToolbarConfig(val showToolbar: Boolean, val title: String, val menu: Int)
    
    data class BottomNavigationConfig(val showBottomNavigation: Boolean)
    
    object UIConfigs {
    
        val uiConfigs = mapOf(
                R.id.fragment_id to UiConfig(ToolbarConfig(true, "Title", R.menu.home), BottomNavigationConfig(false)),
                ...
        )
    
    }
    

    And in our listener when destination changed (onDestinationChanged):

    when (destination.id) {
        R.id.fragment_id -> {
            //Update UI by accessing uiConfigs and getting the info about fragment
           //hide/show BottomNavigation
          //update your shared Toolbar
          //Any shared updates in possible this way
        }
        else -> throw Exception("No config found for ${destination.label}")
    }