web-dev-qa-db-fra.com

Android Composant d'architecture de navigation - Extrait le fragment visible actuel

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.

36
Alin

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.

38
Andrei Toader

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.

20
slhddn

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
        }
    }
}
14
Nicolas Pietri

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());
            }
        });
3
Mukul Bhardwaj

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

3
MoTahir

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
    }
}
2
Tomas Kuhn

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()
1
Aleksandar Ilic

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);
1
Shiam Shabbir Himel

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
0
Abu-Bakr

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.

0
Ranjan

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.

0
Siggy1000

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.

0
miguelt

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)
0
Roque Rueda