Search code examples
androidandroid-fragmentsandroid-architecture-navigationandroid-navigationandroid-jetpack-navigation

How to move to next NavHostFragment?


This should be a really simple problem to solve, but I just can't seem to figure it out.

I'm using the Jetpack navigation architecture components, and I'm having trouble changing which nav graph is being used despite navigating to a different Activity with a different nav graph specified in a different nav host in the layout.

In my app, I have 2 activities; MainActivity.kt and PartyActivity.kt. They are each a container for a FragmentContainerView that is the NavHostFragment for a NavGraph (pre_login_nav_graph.xml and logged_in_nav_graph.xml respectively) to be used only within the context of each of that activity. The navigation all works as expected for MainActivity and pre_login_nav_graph, but when I navigate to PartyActivity, and finish MainActivity, when the new nav host is setup, it doesn't display the correct start destination for logged_in_nav_graph and rather shows the start destination for pre_login_nav_graph.

Extra confusing to me, when I log what the currentDestination is for the nav controller, it claims to be at the correct start destination for logged_in_nav_graph even though it visibly is not! Unless the fragment layout is invisible for some reason, I can't think of a reason why there would be this disconnect between the display and what the nav controller is telling me.

PartyActivity.kt

class PartyActivity : AppCompatActivity() {

    private lateinit var binding: ActivityPartyBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, R.layout.activity_party)
        setupBottomNavBinding()

        // set search as first active tab
        binding.bottomNav.selectedItemId = R.id.searchFragment
    }

    override fun onStart() {
        super.onStart()
        findNavController(R.id.party_nav_host_fragment).navigate(R.id.partyCodeFragment)
        Timber.e("${findNavController(R.id.party_nav_host_fragment).currentDestination}")
        // ^ this logs the expected correct current dest but that fragment isn't shown on screen 
    }

    private fun setupBottomNavBinding() {
        binding.bottomNav.setOnNavigationItemSelectedListener { item ->
            when(item.itemId) {
                R.id.searchFragment,
                R.id.queueFragment,
                R.id.nowPlayingFragment -> {
                    true
//                    NavigationUI
//                        .onNavDestinationSelected(item, party_nav_host_fragment.findNavController())
                }
                else -> {
                    Timber.e("Bottom Nav selection ${item.title} not recognized")
                    false
                }
            }
        }
    }
}

activity_party.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".ui.partyActivity.PartyActivity">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/party_nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toTopOf="@id/bottom_nav"

            app:defaultNavHost="true"
            app:navGraph="@navigation/logged_in_nav_graph" />

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_nav"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            app:labelVisibilityMode="selected"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/bottom_navigation" />

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

logged_in_nav_graph.xml

<?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/logged_in_nav_graph"
    app:startDestination="@id/partyCodeFragment">

    <fragment
        android:id="@+id/partyCodeFragment"
        android:name="com.niehusst.partyq.ui.partyCode.PartyCodeFragment"
        android:label="PartyCodeFragment"
        tools:layout="@layout/party_code_fragment" />
</navigation>

party_code_fragment.xml (the expected start destination for logged_in_nav_graph.xml)

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:background="@color/black"
        tools:context=".ui.partyCode.PartyCodeFragment">

        <!-- TODO: Update blank fragment layout -->
        <TextView
            android:id="@+id/temp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/white"
            android:text="Party code" />

    </LinearLayout>
</layout>

Full codebase is open on github if you want to dig around other files.


Solution

  • Issue turned out to be a typo :( In my fragment PartyCodeFragment I was accidentally trying to inflate the layout with the PartyConnectFragmentBinding. When autocomplete gets it wrong...