Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save zakayothuku/40a5784efc03e7ccd20c9bdfc32345fc to your computer and use it in GitHub Desktop.

Select an option

Save zakayothuku/40a5784efc03e7ccd20c9bdfc32345fc to your computer and use it in GitHub Desktop.

Revisions

  1. @gotev gotev revised this gist Jan 19, 2020. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -188,6 +188,11 @@ class MainActivity : AppCompatActivity() {

    override fun onSupportNavigateUp() =
    navSectionsStateKeeper.onSupportNavigateUp()

    override fun onBackPressed() {
    if (!navSectionsStateKeeper.onSupportNavigateUp())
    super.onBackPressed()
    }
    }
    ```

  2. @gotev gotev revised this gist Jan 18, 2020. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,11 @@ When you switch to a different section and then you come back, you will be exact
    ## Disclaimer
    The solution described here is a temporary workaround with code taken from [NavigationAdvancedSample](https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt), while waiting for JetPack Navigation official multiple backstack support. Check [this tweet](https://twitter.com/alexgt89/status/1218525799252406273?s=09)

    IMHO it's better than a fully handmade custom solution from scratch without JetPack Navigation (you can use nav graphs, view models, safe args, deep links), looking at mid/long range period in a project's maintenance, however take this as a study and experimental material, being sure you understand it fully before applying it to a real production project.
    IMHO it's better than a fully handmade custom solution from scratch without JetPack Navigation:
    - you can use nav graphs, view models, safe args, deep links
    - looking at mid/long range period in a project's maintenance, this is going in the same direction as JetPack

    however take this as a study and experimental material, being sure you understand it fully before applying it to a real production project.

    I followed the principle of:

  3. @gotev gotev revised this gist Jan 18, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ When you switch to a different section and then you come back, you will be exact
    ## Disclaimer
    The solution described here is a temporary workaround with code taken from [NavigationAdvancedSample](https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt), while waiting for JetPack Navigation official multiple backstack support. Check [this tweet](https://twitter.com/alexgt89/status/1218525799252406273?s=09)

    IMHO it's better than a fully handmade custom solution from scratch without JetPack Navigation, looking at mid/long range period in a project's maintenance, however take this as a study and experimental material, being sure you understand it fully before applying it to a real production project.
    IMHO it's better than a fully handmade custom solution from scratch without JetPack Navigation (you can use nav graphs, view models, safe args, deep links), looking at mid/long range period in a project's maintenance, however take this as a study and experimental material, being sure you understand it fully before applying it to a real production project.

    I followed the principle of:

  4. @gotev gotev revised this gist Jan 18, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,7 @@ Copy:
    - `NavigationBottomBarSectionsStateKeeperWorkaround.kt`
    - `NavigationWorkaroundExtensions.kt` -> import your project's R to resolve animations imports

    in your project.
    in your project (both files are in this gist after the README).

    In your activity layout you need to have:
    - `androidx.fragment.app.FragmentContainerView`
  5. @gotev gotev revised this gist Jan 18, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ I followed the principle of:
    [That's an interesting article](https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to)

    since this will be useless once official support in JetPack Navigation is implemented.
    since this will be useless once official support in JetPack Navigation is implemented and you want to keep your codebase as clean as possible.

    >USE THIS AT YOUR OWN RISK. FEEL FREE TO COMMENT IF YOU HAVE SUGGESTIONS FOR IMPROVEMENT OR TO REPORT SOME REAL SCENARIOS WHERE YOU USED IT AND THE OUTCOMES, WHICH CAN SERVE ALSO AS FEEDBACK TO PEOPLE WORKING ON JETPACK NAVIGATION.
  6. @gotev gotev revised this gist Jan 18, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ I followed the principle of:
    [That's an interesting article](https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to)

    however,
    since this will be useless once official support in JetPack Navigation is implemented.

    >USE THIS AT YOUR OWN RISK. FEEL FREE TO COMMENT IF YOU HAVE SUGGESTIONS FOR IMPROVEMENT OR TO REPORT SOME REAL SCENARIOS WHERE YOU USED IT AND THE OUTCOMES, WHICH CAN SERVE ALSO AS FEEDBACK TO PEOPLE WORKING ON JETPACK NAVIGATION.
  7. @gotev gotev revised this gist Jan 18, 2020. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -5,9 +5,9 @@ This mimicks what you can achieve in iOS by using a root `UITabBarController` wi
    When you switch to a different section and then you come back, you will be exactly at the last position you were in that section.

    ## Disclaimer
    The solution described here is a temporary workaround with code taken from [NavigationAdvancedSample](https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt), while waiting for JetPack Navigation official multiple backstack support. Check: https://twitter.com/alexgt89/status/1218525799252406273?s=09
    The solution described here is a temporary workaround with code taken from [NavigationAdvancedSample](https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt), while waiting for JetPack Navigation official multiple backstack support. Check [this tweet](https://twitter.com/alexgt89/status/1218525799252406273?s=09)

    IMHO it's better than a fully handmade custom solution from scratch, looking at mid/long range period in a project's maintenance.
    IMHO it's better than a fully handmade custom solution from scratch without JetPack Navigation, looking at mid/long range period in a project's maintenance, however take this as a study and experimental material, being sure you understand it fully before applying it to a real production project.

    I followed the principle of:

    @@ -17,7 +17,7 @@ I followed the principle of:

    however,

    >USE IT AT YOUR OWN RISK. FEEL FEEL FREE TO COMMENT IF YOU HAVE SUGGESTIONS FOR IMPROVEMENT OR TO REPORT SOME REAL SCENARIOS WHERE YOU USED IT AND THE OUTCOMES.
    >USE THIS AT YOUR OWN RISK. FEEL FREE TO COMMENT IF YOU HAVE SUGGESTIONS FOR IMPROVEMENT OR TO REPORT SOME REAL SCENARIOS WHERE YOU USED IT AND THE OUTCOMES, WHICH CAN SERVE ALSO AS FEEDBACK TO PEOPLE WORKING ON JETPACK NAVIGATION.
    ## License: Apache 2.0
    ```
    @@ -55,7 +55,7 @@ implementation "com.google.android.material:material:1.1.0-rc01"

    Copy:
    - `NavigationBottomBarSectionsStateKeeperWorkaround.kt`
    - `NavigationWorkaroundExtensions.kt`
    - `NavigationWorkaroundExtensions.kt` -> import your project's R to resolve animations imports

    in your project.

  8. @gotev gotev created this gist Jan 18, 2020.
    60 changes: 60 additions & 0 deletions NavigationBottomBarSectionsStateKeeperWorkaround.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,60 @@
    package jetpack.navigation.workaround

    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.Observer
    import androidx.navigation.NavController
    import androidx.navigation.ui.setupActionBarWithNavController
    import com.google.android.material.bottomnavigation.BottomNavigationView
    import java.lang.ref.WeakReference

    class NavigationBottomBarSectionsStateKeeperWorkaround(
    activity: AppCompatActivity,
    private val navHostContainerID: Int,
    private val navGraphIds: List<Int>,
    private val bottomNavigationViewID: Int
    ) {

    private var currentNavController: LiveData<NavController>? = null
    private val activityRef = WeakReference(activity)

    fun onCreate(savedInstanceState: Bundle?) {
    if (savedInstanceState == null) {
    setupBottomNavigationBar()
    } // Else, need to wait for onRestoreInstanceState
    }

    fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    // Now that BottomNavigationBar has restored its instance state
    // and its selectedItemId, we can proceed with setting up the
    // BottomNavigationBar with Navigation
    setupBottomNavigationBar()
    }

    /**
    * Called on first creation and when restoring state.
    */
    private fun setupBottomNavigationBar() {
    val activity = activityRef.get() ?: return

    val bottomNavigationView =
    activity.findViewById<BottomNavigationView>(bottomNavigationViewID)

    val controller = bottomNavigationView.setupWithNavController(
    navGraphIds = navGraphIds,
    fragmentManager = activity.supportFragmentManager,
    containerId = navHostContainerID,
    intent = activity.intent
    )

    // Whenever the selected controller changes, setup the action bar.
    controller.observe(activity, Observer { navController ->
    activity.setupActionBarWithNavController(navController)
    })

    currentNavController = controller
    }

    fun onSupportNavigateUp() = currentNavController?.value?.navigateUp() ?: false
    }
    271 changes: 271 additions & 0 deletions NavigationWorkaroundExtensions.kt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,271 @@
    package jetpack.navigation.workaround

    // Copied from https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt
    // google navigation workaround stuff until multiple back stacks are available

    /*
    * Copyright 2019, The Android Open Source Project
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */

    import android.content.Intent
    import android.util.SparseArray
    import androidx.core.util.forEach
    import androidx.core.util.set
    import androidx.fragment.app.FragmentManager
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.MutableLiveData
    import androidx.navigation.NavController
    import androidx.navigation.fragment.NavHostFragment
    import com.google.android.material.bottomnavigation.BottomNavigationView

    /**
    * Manages the various graphs needed for a [BottomNavigationView].
    *
    * This sample is a workaround until the Navigation Component supports multiple back stacks.
    */
    fun BottomNavigationView.setupWithNavController(
    navGraphIds: List<Int>,
    fragmentManager: FragmentManager,
    containerId: Int,
    intent: Intent
    ): LiveData<NavController> {

    // Map of tags
    val graphIdToTagMap = SparseArray<String>()
    // Result. Mutable live data with the selected controlled
    val selectedNavController = MutableLiveData<NavController>()

    var firstFragmentGraphId = 0

    // First create a NavHostFragment for each NavGraph ID
    navGraphIds.forEachIndexed { index, navGraphId ->
    val fragmentTag =
    getFragmentTag(
    index
    )

    // Find or create the Navigation host fragment
    val navHostFragment =
    obtainNavHostFragment(
    fragmentManager,
    fragmentTag,
    navGraphId,
    containerId
    )

    // Obtain its id
    val graphId = navHostFragment.navController.graph.id

    if (index == 0) {
    firstFragmentGraphId = graphId
    }

    // Save to the map
    graphIdToTagMap[graphId] = fragmentTag

    // Attach or detach nav host fragment depending on whether it's the selected item.
    if (this.selectedItemId == graphId) {
    // Update livedata with the selected graph
    selectedNavController.value = navHostFragment.navController
    attachNavHostFragment(
    fragmentManager,
    navHostFragment,
    index == 0
    )
    } else {
    detachNavHostFragment(
    fragmentManager,
    navHostFragment
    )
    }
    }

    // Now connect selecting an item with swapping Fragments
    var selectedItemTag = graphIdToTagMap[this.selectedItemId]
    val firstFragmentTag = graphIdToTagMap[firstFragmentGraphId]
    var isOnFirstFragment = selectedItemTag == firstFragmentTag

    // When a navigation item is selected
    setOnNavigationItemSelectedListener { item ->
    // Don't do anything if the state is state has already been saved.
    if (fragmentManager.isStateSaved) {
    false
    } else {
    val newlySelectedItemTag = graphIdToTagMap[item.itemId]
    if (selectedItemTag != newlySelectedItemTag) {
    // Pop everything above the first fragment (the "fixed start destination")
    fragmentManager.popBackStack(
    firstFragmentTag,
    FragmentManager.POP_BACK_STACK_INCLUSIVE
    )
    val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
    as NavHostFragment

    // Exclude the first fragment tag because it's always in the back stack.
    if (firstFragmentTag != newlySelectedItemTag) {
    // Commit a transaction that cleans the back stack and adds the first fragment
    // to it, creating the fixed started destination.
    fragmentManager.beginTransaction()
    .setCustomAnimations(
    R.anim.nav_default_enter_anim,
    R.anim.nav_default_exit_anim,
    R.anim.nav_default_pop_enter_anim,
    R.anim.nav_default_pop_exit_anim
    )
    .attach(selectedFragment)
    .setPrimaryNavigationFragment(selectedFragment)
    .apply {
    // Detach all other Fragments
    graphIdToTagMap.forEach { _, fragmentTagIter ->
    if (fragmentTagIter != newlySelectedItemTag) {
    detach(fragmentManager.findFragmentByTag(firstFragmentTag)!!)
    }
    }
    }
    .addToBackStack(firstFragmentTag)
    .setReorderingAllowed(true)
    .commit()
    }
    selectedItemTag = newlySelectedItemTag
    isOnFirstFragment = selectedItemTag == firstFragmentTag
    selectedNavController.value = selectedFragment.navController
    true
    } else {
    false
    }
    }
    }

    // Optional: on item reselected, pop back stack to the destination of the graph
    setupItemReselected(graphIdToTagMap, fragmentManager)

    // Handle deep link
    setupDeepLinks(navGraphIds, fragmentManager, containerId, intent)

    // Finally, ensure that we update our BottomNavigationView when the back stack changes
    fragmentManager.addOnBackStackChangedListener {
    if (!isOnFirstFragment && !fragmentManager.isOnBackStack(firstFragmentTag)) {
    this.selectedItemId = firstFragmentGraphId
    }

    // Reset the graph if the currentDestination is not valid (happens when the back
    // stack is popped after using the back button).
    selectedNavController.value?.let { controller ->
    if (controller.currentDestination == null) {
    controller.navigate(controller.graph.id)
    }
    }
    }
    return selectedNavController
    }

    private fun BottomNavigationView.setupDeepLinks(
    navGraphIds: List<Int>,
    fragmentManager: FragmentManager,
    containerId: Int,
    intent: Intent
    ) {
    navGraphIds.forEachIndexed { index, navGraphId ->
    val fragmentTag =
    getFragmentTag(
    index
    )

    // Find or create the Navigation host fragment
    val navHostFragment =
    obtainNavHostFragment(
    fragmentManager,
    fragmentTag,
    navGraphId,
    containerId
    )
    // Handle Intent
    if (navHostFragment.navController.handleDeepLink(intent)
    && selectedItemId != navHostFragment.navController.graph.id
    ) {
    this.selectedItemId = navHostFragment.navController.graph.id
    }
    }
    }

    private fun BottomNavigationView.setupItemReselected(
    graphIdToTagMap: SparseArray<String>,
    fragmentManager: FragmentManager
    ) {
    setOnNavigationItemReselectedListener { item ->
    val newlySelectedItemTag = graphIdToTagMap[item.itemId]
    val selectedFragment = fragmentManager.findFragmentByTag(newlySelectedItemTag)
    as NavHostFragment
    val navController = selectedFragment.navController
    // Pop the back stack to the start destination of the current navController graph
    navController.popBackStack(
    navController.graph.startDestination, false
    )
    }
    }

    private fun detachNavHostFragment(
    fragmentManager: FragmentManager,
    navHostFragment: NavHostFragment
    ) {
    fragmentManager.beginTransaction()
    .detach(navHostFragment)
    .commitNow()
    }

    private fun attachNavHostFragment(
    fragmentManager: FragmentManager,
    navHostFragment: NavHostFragment,
    isPrimaryNavFragment: Boolean
    ) {
    fragmentManager.beginTransaction()
    .attach(navHostFragment)
    .apply {
    if (isPrimaryNavFragment) {
    setPrimaryNavigationFragment(navHostFragment)
    }
    }
    .commitNow()
    }

    private fun obtainNavHostFragment(
    fragmentManager: FragmentManager,
    fragmentTag: String,
    navGraphId: Int,
    containerId: Int
    ): NavHostFragment {
    // If the Nav Host fragment exists, return it
    val existingFragment = fragmentManager.findFragmentByTag(fragmentTag) as NavHostFragment?
    existingFragment?.let { return it }

    // Otherwise, create it and return it.
    val navHostFragment = NavHostFragment.create(navGraphId)
    fragmentManager.beginTransaction()
    .add(containerId, navHostFragment, fragmentTag)
    .commitNow()
    return navHostFragment
    }

    private fun FragmentManager.isOnBackStack(backStackName: String): Boolean {
    val backStackCount = backStackEntryCount
    for (index in 0 until backStackCount) {
    if (getBackStackEntryAt(index).name == backStackName) {
    return true
    }
    }
    return false
    }

    private fun getFragmentTag(index: Int) = "bottomNavigation#$index"
    190 changes: 190 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,190 @@
    # Android JetPack Navigation + Material BottomNavigationView keeping sections navigation state

    This mimicks what you can achieve in iOS by using a root `UITabBarController` with a `UINavigationController` for each section.

    When you switch to a different section and then you come back, you will be exactly at the last position you were in that section.

    ## Disclaimer
    The solution described here is a temporary workaround with code taken from [NavigationAdvancedSample](https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt), while waiting for JetPack Navigation official multiple backstack support. Check: https://twitter.com/alexgt89/status/1218525799252406273?s=09

    IMHO it's better than a fully handmade custom solution from scratch, looking at mid/long range period in a project's maintenance.

    I followed the principle of:

    >Write code that's easy to delete, not easy to extend
    [That's an interesting article](https://programmingisterrible.com/post/139222674273/write-code-that-is-easy-to-delete-not-easy-to)

    however,

    >USE IT AT YOUR OWN RISK. FEEL FEEL FREE TO COMMENT IF YOU HAVE SUGGESTIONS FOR IMPROVEMENT OR TO REPORT SOME REAL SCENARIOS WHERE YOU USED IT AND THE OUTCOMES.
    ## License: Apache 2.0
    ```
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
    ```

    ## Recipe
    Create a new project or open an existing one. You need the following dependencies:

    ```groovy
    def lifecycle_version = "2.2.0-rc03"
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    def nav_version = "2.2.0-rc04"
    implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
    implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
    // Support
    implementation "androidx.appcompat:appcompat:1.1.0"
    implementation "androidx.constraintlayout:constraintlayout:2.0.0-beta4"
    implementation "com.google.android.material:material:1.1.0-rc01"
    ```

    Copy:
    - `NavigationBottomBarSectionsStateKeeperWorkaround.kt`
    - `NavigationWorkaroundExtensions.kt`

    in your project.

    In your activity layout you need to have:
    - `androidx.fragment.app.FragmentContainerView`
    - `com.google.android.material.bottomnavigation.BottomNavigationView`

    Example:

    `activity_main.xml`:
    ```xml
    <?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:animateLayoutChanges="true"
    android:theme="@style/AppTheme.AppBarOverlay"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

    <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/bottom_navigation"
    app:layout_constraintTop_toBottomOf="@id/appbar" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navigation"
    style="@style/Widget.MaterialComponents.BottomNavigationView.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:menu="@menu/main_bottombar" />

    </androidx.constraintlayout.widget.ConstraintLayout>
    ```

    Then, create the menu which contains the bottom bar items. Example:

    `main_bottombar.xml`
    ```xml
    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
    android:id="@+id/nav_section1"
    android:icon="@android:drawable/ic_menu_call"
    android:title="Section 1" />

    <item
    android:id="@+id/nav_section2"
    android:icon="@android:drawable/ic_menu_add"
    android:title="Section 2" />

    <item
    android:id="@+id/nav_section3"
    android:icon="@android:drawable/ic_menu_camera"
    android:title="Section 3" />
    </menu>
    ```

    Create one nav graph for each section in the tab bar. In this example, the 3 nav graphs must be called:
    ```
    nav_section1
    nav_section2
    nav_section3
    ```
    because for the link between the bottom bar and the sections to work, `main_bottombar menu IDs must match navigation graph IDs`.

    Populate each section with your navigation items and don't forget to set every `startDestination`.

    now in your `MainActivity.kt` add:

    ```kotlin
    class MainActivity : AppCompatActivity() {
    private val navSectionsStateKeeper by lazy {
    NavigationBottomBarSectionsStateKeeperWorkaround(
    activity = this,
    navHostContainerID = R.id.nav_host_fragment,
    navGraphIds = listOf(
    R.navigation.nav_section1,
    R.navigation.nav_section2,
    R.navigation.nav_section3
    ),
    bottomNavigationViewID = R.id.bottom_navigation
    )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    setSupportActionBar(toolbar)
    supportActionBar?.apply {
    setDisplayHomeAsUpEnabled(true)
    setDisplayShowHomeEnabled(true)
    }

    navSectionsStateKeeper.onCreate(savedInstanceState)
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    navSectionsStateKeeper.onRestoreInstanceState(savedInstanceState)
    }

    override fun onSupportNavigateUp() =
    navSectionsStateKeeper.onSupportNavigateUp()
    }
    ```

    Run and enjoy :tada: