How I can retrieve current fragment in NavHostFragment?
Solution 1
Reference to the displayed fragment (AndroidX):
java
public Fragment getForegroundFragment(){
Fragment navHostFragment = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
return navHostFragment == null ? null : navHostFragment.getChildFragmentManager().getFragments().get(0);
}
kotlin
val navHostFragment: Fragment? =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment)
navHostFragment?.childFragmentManager?.fragments?.get(0)
Here nav_host_fragment
is an ID
of the fragment
tag in your activity_main.xml
with android:name="androidx.navigation.fragment.NavHostFragment"
Solution 2
Navigation does not provide any mechanism for getting the implementation (i.e., the Fragment itself) of the current destination.
As per the Creating event callbacks to the activity, you should either communicate with your Fragment by
- Having the Fragment register a callback in its
onAttach
method, casting your Activity to an instance of an interface you provide -
Use a shared
ViewModel
that your Activity and Fragment use to communicate.
Solution 3
You can do something like this:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val navHostFragment = supportFragmentManager.fragments.first() as? NavHostFragment
if(navHostFragment != null) {
val childFragments = navHostFragment.childFragmentManager.fragments
childFragments.forEach { fragment ->
fragment.onActivityResult(requestCode, resultCode, data)
}
}
}
But for more advanced communication Listeners with callback methods registered in Fragment.onAttach() (Fragment -> Activity rather one direction communication
) and SharedViewModel (bidirectional
, important to have ViewModelProviders, and Lifecycle owner that is scoped to getActivity()
rather)
Solution 4
Based on other answers
Fragment navHostFragment = getSupportFragmentManager().getPrimaryNavigationFragment();
Fragment fragment = navHostFragment.getChildFragmentManager().getFragments().get(0);
((Your Fragment Class) fragment).(public method inside the fragment)
worked for me
Solution 5
Using Michal's answer I wrote this extension function for testing:
@Suppress("UNCHECKED_CAST")
fun <F : Fragment> AppCompatActivity.getFragment(fragmentClass: Class<F>): F? {
val navHostFragment = this.supportFragmentManager.fragments.first() as NavHostFragment
navHostFragment.childFragmentManager.fragments.forEach {
if (fragmentClass.isAssignableFrom(it.javaClass)) {
return it as F
}
}
return null
}
Used like this:
val myFragment = activity.getFragment(MyFragment::class.java)
BenjaminBihr
Updated on July 09, 2022Comments
-
BenjaminBihr almost 2 years
I tried to find a method in the new Navigation components but I didn't find anything about that.
I have the current destination with :
mainHostFragment.findNavController().currentDestination
But I can't get any reference to the displayed fragment.
-
Sever about 5 yearsAll links show how to communicate between fragments. But how we can call fragment method from activity if navigation does not provide any mechanism for getting the implementation of the current destination?
-
ianhanniballake about 5 years@Sever - see this issue and how to use
getPrimaryNavigationFragment()
to retrieve the current Fragment. -
Sever about 5 yearsBig thanks. It works. val navHostFragment = supportFragmentManager.primaryNavigationFragment as NavHostFragment val yourFragment = currentFragmentClassName.childFragmentManager.primaryNavigationFragment as YourFragment
-
drdaanger over 4 yearsYou can squish this down to
inline fun <reified T : Fragment> FragmentManager.findFragmentByClass(): T? = fragments.firstOrNull { it is T } as T?
-
isabsent over 4 years@ianhanniballake: Sorry, I didn't understand is there a way to get the foreground fragment by means of
getPrimaryNavigationFragment()
now or they are going to provide such opportunity in the future only!? -
Miha_x64 about 3 yearsWell, to share ViewModel between two fragments, one of them must be its owner. And the other one must find that owner in order to fetch that ViewModel. So… just never use Navigation, it's retarded.
-
carl about 3 yearsIt is incomprehensible why Navigation does not maintain a list of fragments, for example needed when MainActivity wants to call a method in a child fragment. In consequence, you need to use the "good old ways" for that, and then, whats the point of introducing a Navigation system? I don@t get it.
-
Shalbert over 2 yearsYou can remove
as? NavHostFragment
and make the if-statementif (navHostFragment is NavHostFragment)
-
Milad Faridnia almost 2 yearsin my case ?.childFragmentManager?.fragments?.last() gives me current fragment
-
John Glen almost 2 yearsWow, hacky answers. childFragmentManager.findFragmentById exists.