Avant d’essayer le composant Navigation, j’ai utilisé manuellement les transactions de fragment et utilisé la balise fragment pour extraire le fragment en cours.
val fragment:MyFragment = supportFragmentManager.findFragmentByTag(tag):MyFragment
Maintenant, dans ma structure d'activité principale, j'ai quelque chose comme:
<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"
/>
Comment puis-je récupérer le fragment actuellement affiché par le composant Navigation? Faire
supportFragmentManager.findFragmentById(R.id.nav_Host)
retourne un NavHostFragment
et je veux récupérer mon 'MyFragment` affiché.
Je vous remercie.
J'ai réussi à trouver un moyen pour l'instant et c'est comme suit:
NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_Host);
navHostFragment.getChildFragmentManager().getFragments().get(0);
Bien sûr, vous savez que c'est le premier fragment. Je suis toujours à la recherche d'une solution sans cela. Je conviens que ce n'est pas la meilleure solution, mais cela devrait être quelque chose pour le moment.
Je ne trouve aucun moyen de récupérer l'instance de fragment en cours. Cependant, vous pouvez obtenir l'ID du dernier fragment ajouté en utilisant le code ci-dessous.
navController.getCurrentDestination().getId()
Il retourne l'ID dans le fichier de navigation. J'espère que cela t'aides.
Vous devez rechercher la propriété childFragmentManager primaryNavigationFragment de votre fragment de navigation, le fragment actuellement affiché est référencé.
val navHost = supportFragmentManager.findFragmentById(R.id.main_nav_fragment)
navHost?.let { navFragment ->
navFragment.childFragmentManager.primaryNavigationFragment?.let {fragment->
//DO YOUR STUFF
}
}
}
Utilisez addOnDestinationChangedListener
dans une activité ayant 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());
}
});
cela pourrait être en retard, mais pour ceux qui cherchent encore
val currentfraagment=NavHostFragment.findNavController(nav_Host_fragment).currentDestination!!.id
alors vous pouvez faire quelque chose comme
if(currentfraagment == R.id.myFragemnt){
//do something
}
notez qu'il s'agit de kotlin, le code Java devrait être presque identique
Solution de travail trouvée.
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
}
}
Cela semble être la solution la plus propre.
1. Créez l'extension suivante
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
fun FragmentManager.getCurrentNavigationFragment(): Fragment? =
primaryNavigationFragment?.childFragmentManager?.fragments?.first()
2. Dans Activity
avec NavHostFragment
utilisez-le comme ceci:
val currentFragment = supportFragmentManager.getCurrentNavigationFragment()
pouvez-vous s'il vous plaît vérifier avec getChildFragmentManager()
appel avec
NavHostFragment fragment = supportFragmentManager.findFragmentById(R.id.nav_Host);
MyFragment frag = (MyFragment) fragment.getChildFragmentManager().findFragmentByTag(tag);
D'abord, vous obtenez le fragment actuel par identifiant, puis vous pouvez le trouver en fonction de cet identifiant.
int id = navController.getCurrentDestination().getId();
Fragment fragment = getSupportFragmentManager().findFragmentById(id)l
Faire :
• dans un bouton de votre fragment:
val navController = findNavController(this)
navController.popBackStack()
• Dans votre activité 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()
}
Dans votre activité, définissez un objet fragment. Et à partir de chaque fragment, appelez cette méthode en transmettant un objet fragment, comme si l'objet fragment statique était remplacé par le fragment en cours d'affichage à chaque fois.
//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>;
Vous pouvez également définir des rappels de fragment en activité pour une meilleure approche et transmettre votre objet fragment actuel.
J'ai combiné Andrei Toaders répond et Mukul Bhardwajs répond avec un OnBackStackChangedListener
.
En tant qu'attribut:
private FooFragment fragment;
Dans mon 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;
}
});
De cette façon, je peux obtenir un fragment, qui sera affiché plus tard. On peut même être capable de boucler si frags
et de vérifier plusieurs fragments avec instanceof
.
Le meilleur moyen d'y parvenir est d'enregistrer un rappel de cycle de vie de fragment.
Conformément à la question initiale, si votre NavHostFragment
est défini comme ...
<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"
/>
Ensuite, dans votre activité principale 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
}
}
)
D'autres méthodes de rappel peuvent être remplacées pour répondre à vos besoins.
Je dois faire cela pour configurer une vue de navigation inférieure et je l’ai fait comme suit:
val navController = Navigation.findNavController(requireActivity(), R.id.nav_tabs_home)
val bottomNavBar: BottomNavigationView = nav_content_view
NavigationUI.setupWithNavController(bottomNavBar, navController)