问题
Before trying the Navigation component I used to manually do fragment transactions and used the fragment tag in order to fetch the current fragment.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Now in my main activity layout I have something like:
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_host"
app:navGraph= "@navigation/nav_item"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost= "true"
/>
How can I retrieve the current displayed fragment by the Navigation component? Doing
supportFragmentManager.findFragmentById(R.id.nav_host)
returns a NavHostFragment
and I want to retrieve my shown 'MyFragment`.
Thank you.
回答1:
I managed to discover a way for now and it is as follows:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
In case of course you know it is the first fragment. I am still investigating a way without this. I agree it is not the best way but that should be something for now.
回答2:
There is no way I can find to retrieve the current fragment instance. However, you can get the ID of lastly added fragment using the code below.
navController.getCurrentDestination().getId()
It returns the ID in navigation file. Hope this helps.
回答3:
You should look the childFragmentManager primaryNavigationFragment property of your nav fragment, this is where the current displayed fragment is referenced.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
navHost?.let { navFragment ->
navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
//DO YOUR STUFF
}
}
}
回答4:
Use addOnDestinationChangedListener
in activity having NavHostFragment
NavController navController= Navigation.findNavController(MainActivity.this,R.id.your_nav_host);
navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
Log.e(TAG, "onDestinationChanged: "+destination.getLabel());
}
});
回答5:
this might be late but for anyone who's still looking
val currentfraagment=NavHostFragment.findNavController(nav_host_fragment).currentDestination!!.id
then you can do something like
if(currentfraagment == R.id.myFragemnt){
//do something
}
note that this is for kotlin, java code should be almost the same
回答6:
This seems like the cleanest solution.
1. Create the following extension
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
fun FragmentManager.getCurrentNavigationFragment(): Fragment? =
primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2. In Activity
with NavHostFragment
use it like this:
val currentFragment = supportFragmentManager.getCurrentNavigationFragment()
回答7:
Found working solution.
private fun getCurrentFragment(): Fragment? {
val currentNavHost = supportFragmentManager.findFragmentById(R.id.nav_host_id)
val currentFragmentClassName = ((this as NavHost).navController.currentDestination as FragmentNavigator.Destination).className
return currentNavHost?.childFragmentManager?.fragments?.filterNotNull()?.find {
it.javaClass.name == currentFragmentClassName
}
}
回答8:
can you please check with getChildFragmentManager()
call with
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
回答9:
If you need the instance of your fragment, you can go with:
(Activity) => supportFragmentManager.fragments.first().childFragmentManager.fragments.first()
It's very ugly but from there you can check if it's an instance of the fragment you want to play around with
回答10:
In your activity define a fragment object. And from each fragment call this method by passing fragment object, like So the static fragment object will be overridden by current showing fragment every time.
//method in MainActivity
private static Fragment fragment;
public void setFragment(Fragment fragment){
this.fragment = fragment;
}
//And from your fragment class, you can call
((<yourActivity in which fragment present>)getActivity()).setFragment(<your fragment object>);
//if you want to set it directly;
((<yourActivity in which fragment present>)getActivity()).fragment=<your fragment object>;
You can also set callback from fragment to activity, for a better approach and pass your current fragment object.
回答11:
I combined Andrei Toaders answer and Mukul Bhardwajs answer with an OnBackStackChangedListener
.
As an attribute:
private FooFragment fragment;
In my onCreate
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host);
FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager();
FragmentManager.OnBackStackChangedListener listener = () -> {
List<Fragment> frags = navHostManager.getFragments();
if(!frags.isEmpty()) {
fragment = (FooFragment) frags.get(0);
}
};
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
if(destination.getId()==R.id.FooFragment){
navHostManager.addOnBackStackChangedListener(listener);
} else {
navHostManager.removeOnBackStackChangedListener(listener);
fragment = null;
}
});
This way i can get a fragment, which will be displayed later on.
One even may be able to loop though frags
and check multiple fragments with instanceof
.
回答12:
I need to do this to setup a bottom navigation view and I did it this way:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
val bottomNavBar: BottomNavigationView = nav_content_view
NavigationUI.setupWithNavController(bottomNavBar, navController)
回答13:
First, you get the current fragment by id, then you can find the fragment, depending on that id.
int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id)l
回答14:
The best way to achieve this is to register a fragment lifecycle callback.
As per the original question, if your NavHostFragment
is defined as...
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_host"
app:navGraph= "@navigation/nav_item"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost= "true"
/>
Then in your main activity onCreate(..)
...
nav_host.childFragmentManager.registerFragmentLifecycleCallbacks(
object:FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentViewCreated(
fm: FragmentManager, f: Fragment, v: View,
savedInstanceState: Bundle?
) {
// callback method always called whenever a
// fragment is added, or, a back-press returns
// to the start-destination
}
}
)
Other callback methods may be overridden to fit your requirements.
回答15:
Make :
• in some button in your fragment:
val navController = findNavController(this)
navController.popBackStack()
• In your Activity onBackPressed()
override fun onBackPressed() {
val navController = findNavController(R.id.nav_host_fragment)
val id = navController.currentDestination?.getId()
if (id == R.id.detailMovieFragment){
navController.popBackStack()
return
}
super.onBackPressed()
}
回答16:
On Androidx, I have tried many methods for finding out required fragment from NavHostFragment
. Finally I could crack it with below method
public Fragment getFunctionalFragment (String tag_name)
{
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
FragmentManager navHostManager = Objects.requireNonNull(navHostFragment).getChildFragmentManager();
Fragment fragment=null;
List fragment_list = navHostManager.getFragments();
for (int i=0; i < fragment_list.size() ; i ++ )
{
if ( fragment_list.get(i) instanceof HomeFragment && tag_name.equals("frg_home")) {
fragment = (HomeFragment) fragment_list.get(i);
break;
}
}
return fragment;
}
回答17:
navController().currentDestination?.id
will give you your current Fragment
's id where
private fun navController() = Navigation.findNavController(this, R.id.navHostFragment)
this id is the id which you have given in your Navigation Graph XML
file under fragment
tag. You could also compare currentDestination.label
if you want.
来源:https://stackoverflow.com/questions/51385067/android-navigation-architecture-component-get-current-visible-fragment