Reputation: 313
In my Android project I have a very simple Navigation Graph, including two fragments: Master and Detail:
<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"
app:startDestination="@id/wordsListFragment">
<fragment
android:id="@+id/wordsListFragment"
android:name="com.***.presentation.view.WordsListFragment"
android:label="List"
tools:layout="@layout/words_list_fragment">
<action
android:id="@+id/action_wordsListFragment_to_wordDetailsFragment"
app:destination="@id/wordDetailsFragment" />
</fragment>
<fragment
android:id="@+id/wordDetailsFragment"
android:name="com.***.presentation.view.WordDetailsFragment"
android:label="Details"
tools:layout="@layout/word_details_fragment" />
</navigation>
The navigation itself works perfectly fine in both directions including the "Back" behaviour.
In that project I have a single activity where I implement OnDestinationChangedListener
.
All this according to the following documentation from Google: NavController Updating UI
I call the following method when the user clicks on a list item (while being on the master fragment):
findNavController().navigate(R.id.action_wordsListFragment_to_wordDetailsFragment, null)
Then in the parent activity I have the following implementation:
private fun setupNavController() {
navigationController = findNavController(R.id.nav_mainhost_fragment_container)
navigationController.addOnDestinationChangedListener(mainDestinationChangedListener)
appBarConfiguration = AppBarConfiguration(navigationController.graph)
setupActionBarWithNavController(navigationController, appBarConfiguration)
}
and that is the listener object:
private val mainDestinationChangedListener =
NavController.OnDestinationChangedListener { controller, destination, arguments ->
if (destination.id == R.id.action_wordsListFragment_to_wordDetailsFragment) {
actionBar?.hide()
} else {
actionBar?.show()
}
}
but the destination.id
does not match the R.id.action_wordsListFragment_to_wordDetailsFragment
I have tried to clean up the project, clean up the IDE cache, the gradle cache, but the generated identifiers still does not match. I have also tried to use Navigation via Safe Args:
val action = WordsListFragmentDirections.actionWordsListFragmentToWordDetailsFragment()
findNavController().navigate(action)
but the results in the given listener are always the same (i.e. not matching).
Some values from debugging:
findNavController().navigate(1000021) //R.id.action_wordsListFragment_to_wordDetailsFragment
but the next call on stack has another value:
what also matches the destination.id
values passed to the OnDestinationChangedListener
:
destination.id //2131231018
Any hints from your side are more than welcome. I just want to recognise the destination or the action ID and adjust the ToolBar accordingly.
Upvotes: 22
Views: 15554
Reputation: 381
I was also facing this, for me the solution was something like this
com.dainikbhaskar.features.videofeed.R.id.video_feed_dest -> 2131297511 where as R.id.video_feed_dest -> 1000296
i have multimodule project structure.. check we first one.. with full package import not from app module..
Upvotes: -1
Reputation: 209
The issue is with the Android studio debugger. If I print the value in logcat or assign it to a variable, then the value is 2XXXXXXXXX but if I evaluate with debugger then the value is 1XXXXXX.
I have checked the action id(R.id.xxxx) hex code in the APK. When I convert the hex code into integer, it gives a value in 2XXXXXXXXX which is equal to the value that got printed in the logcat
Upvotes: 6
Reputation: 605
The above solution does not work, Instead of matching on the destination fragment id, you can match on the fully qualified class name of the destination fragment, your code becomes
navController.addOnDestinationChangedListener{ nc: NavController, nd: NavDestination, args: Bundle? ->
val destinationClassName = (nc.currentDestination as FragmentNavigator.Destination).className
when(destinationClassName) {
"com.*domainName.*PackageName.*className" -> {
"Do you thing here"
}
else -> {
"Cater for the else block here"
}
}
}
Upvotes: -1
Reputation: 3320
You are comparing fragmentId with actionId so it's always false
here if (destination.id == R.id.action_wordsListFragment_to_wordDetailsFragment)
As destination.id
is fragmentId
and
R.id.action_wordsListFragment_to_wordDetailsFragment
is actionId
To make it work you should compare two fragment ids like
if (destination.id == R.id.wordDetailsFragment)
*Edit
First you should find you navControler , then listen to its destination change.
val navController = findNavController(this,R.id.nav_host_fragment)// this maybe change
navController.addOnDestinationChangedListener { controller, destination, arguments ->
if(destination.id == R.id.wordDetailsFragment) {
actionBar?.hide()
} else {
actionBar?.show()
}
}
Upvotes: 18