2

So my app's architecture is kind of unique, I am using Navigation Components btw.

It has a main activity that has a NavHostFragment associated with. The NavHostFragment has navigation graph associated with it which has two fragments, Main Fragment (as the start destination) and Settings Fragment (accessible with the menu item in toolbar). Now the Main Fragments acts as another host for another NavHostFragment. So here's what that looks like:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.fragments.MainFragment">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/child_nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation_bar"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/child_nav_graph" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation_bar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

Note that there's a bottom navigation bar at the bottom of the Main Fragment but there's no such bottom navigation bar in the Main Activity. Also note that the Main Fragment has another NavHostFragment which points to a different Navigation Graph.

Here's the Main Activity's layout file:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.main.MainActivity">

    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/materialToolbar"
        style="@style/Widget.MaterialComponents.Toolbar.Primary"
        android:layout_width="0dp"
        android:layout_height="?actionBarSize"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/parent_nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/materialToolbar"
        app:navGraph="@navigation/main_nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

Here's the main_nav_graph:

<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
    android:id="@+id/main_nav_graph"
    app:startDestination="@id/main_fragment">
    <fragment
        android:id="@+id/settings_fragment"
        android:name="com.dbtechprojects.cloudstatustest.ui.main.fragments.SettingsFragment"
        android:label="Settings"
        tools:layout="@layout/fragment_settings" />
    <fragment
        android:id="@+id/main_fragment"
        android:name="com.dbtechprojects.cloudstatustest.ui.main.fragments.MainFragment"
        android:label="Welcome"
        tools:layout="@layout/fragment_main" />
</navigation>

and here's the child_nav_graph

<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
    android:id="@+id/main_nav_graph"
    app:startDestination="@id/aws_fragment">

    <fragment
        android:id="@+id/aws_fragment"
        android:name="com.dbtechprojects.cloudstatustest.ui.main.fragments.AwsFragment"
        android:label="AWS"
        tools:layout="@layout/fragment_aws" />

    <fragment
        android:id="@+id/azure_fragment"
        android:name="com.dbtechprojects.cloudstatustest.ui.main.fragments.AzureFragment"
        android:label="Azure"
        tools:layout="@layout/fragment_azure" />

    <fragment
        android:id="@+id/gcp_fragment"
        android:name="com.dbtechprojects.cloudstatustest.ui.main.fragments.GcpFragment"
        android:label="GCP"
        tools:layout="@layout/fragment_gcp" />
</navigation>

So as you can see, the Main Fragment is what hosts the three other Fragments that are mapped with the Bottom Nav Bar. I am using this approach because I wanted my Settings Fragment to hide the Bottom Nav Bar when I navigate to it. Now the bottom nav bar shows in all the three fragments that I want them to be shown in but not in the settings fragment as I expect it to.

Now here's the problem, when I open the app, the Main Fragment is shown. The Main Fragment, contains the bottom nav bar when I select one of the items in the bottom nav bar, it correctly navigates to the right fragment. But when I go the settings fragment and then come back, the bottom nav bar stops working. Here's a video showing the behavior: https://i.stack.imgur.com/QtkBF.jpg

Here's MainActivity.kt: https://gist.github.com/ac65ae323ca771d064562d18d9fac880 Here's the MainFragment.kt: https://gist.github.com/c700e33b4f04e078abf8c94db9bb6faf

Sbeve
  • 91
  • 2
  • 16
  • If you are using Navigation Components then you can set condition to hide / show Bottom Navigation view to be shows in which fragment. – Parth Patel May 31 '21 at 12:01
  • That wouldn't be ideal since i want an animation to be shown that makes it feel like the settings fragment is covering the bottom nav bar. – Sbeve May 31 '21 at 12:09
  • You can apply animation to fragment as well. OR you can set animation to BottomView for hiding with animation – Parth Patel May 31 '21 at 12:12
  • but whats wrong with my current approach? i don't understand why its not working – Sbeve May 31 '21 at 12:13
  • It seems your Main Navigation controller might be reset or we need to debug it to find the actual cause. – Parth Patel May 31 '21 at 12:18
  • Do you mean `childNavController`? because the bnv doesn't use the mainNavController. – Sbeve May 31 '21 at 12:24
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/233131/discussion-between-sbeve-sbren-and-parth-patel). – Sbeve May 31 '21 at 12:44

2 Answers2

0

The problem was in my MainFragment

    val bottomNavBar by lazy {
        binding.bottomNavigationBar
    }

instead of doing, i should have directly referred to the bnv using binding.bottomNavigationBar everywhere. That fixed it.

Sbeve
  • 91
  • 2
  • 16
  • I'm trying to do a similar approach but I had a problem of moving to fragment in the list of fragments of bottom navigation to activity fragments hope if you can help https://stackoverflow.com/questions/68521717/failed-to-move-to-parent-fragment-in-nested-child-navigation-component –  Jul 26 '21 at 12:25
0

when beginning transaction for a new fragment, do not add add

addtobackstack()

instead use this

if (my_cart == null) {
                my_cart = new My_Cart();
                fragmentManager.beginTransaction()
                        .hide(currentFragment)
                        .add(R.id.main_fragment, my_cart)
                        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
                        .commit();
            } else {
                fragmentManager.beginTransaction().hide(currentFragment).show(my_cart).setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit();
            }
            currentFragment = my_cart;
VIVek
  • 121
  • 1
  • 4