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.
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...