Comment obtenir le fragment actuellement affiché?

448

Je joue avec des fragments dans Android.

Je sais que je peux modifier un fragment en utilisant le code suivant:

FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction fragTrans = fragMgr.beginTransaction();

MyFragment myFragment = new MyFragment(); //my custom fragment

fragTrans.replace(android.R.id.content, myFragment);
fragTrans.addToBackStack(null);
fragTrans.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragTrans.commit();

Ma question est, dans un fichier Java, comment puis-je obtenir l'instance de fragment actuellement affichée?

Leem.fin
la source
1
Copie

Réponses:

454

Lorsque vous ajoutez le fragment dans votre transaction, vous devez utiliser une balise.

fragTrans.replace(android.R.id.content, myFragment, "MY_FRAGMENT");

... et plus tard si vous souhaitez vérifier si le fragment est visible:

MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("MY_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
   // add your code here
}

Voir également http://developer.android.com/reference/android/app/Fragment.html

ramdroid
la source
74
D'accord, mais j'ai besoin d'un moyen pour obtenir immédiatement l'instance de fragment actuellement affichée, pas pour vérifier itérativement tous les fragments, puis pour décider quel fragment est maintenant affiché à l'écran. Je pense que votre réponse a besoin de mon code pour vérifier itérativement chacun de mes fragments, et trouver celui visible ...
Leem.fin
33
Oui, mais il pourrait y avoir plus d'un fragment visible à la fois. Il n'y a donc rien de tel que le "seul fragment actif" ....
ramdroid
6
Ok, même s'il y a plusieurs fragments affichés, j'ai toujours besoin d'un moyen pour les obtenir ... et d'un moyen qui est meilleur que de vérifier itérativement chacun de mes fragments. Je m'inquiète de "leur faire" une méthode comme getDisplayedFragment (), mais je ne suis pas sûr qu'il existe une telle méthode dans Android
Leem.fin
2
Je ne sais pas pourquoi c'est un problème pour vous ... Vous n'avez généralement que quelques fragments dans une activité et cela ne devrait pas vraiment être un problème de les vérifier s'ils sont visibles ou non.
ramdroid
13
Pourquoi tout le monde vote-t-il cette réponse? Bien sûr, c'est un bon morceau de code mais ne répond pas à la question pour obtenir un fragment spécifique par tag. MAIS Asker veut le fragment actuellement affiché, ce qui signifie qu'il ne sait pas quel fragment est affiché. Oui, il peut y avoir plusieurs fragments, mais la lecture de la question n'indique qu'un seul fragment est affiché sur l'interface utilisateur .... Désolé, il a fallu diminuer le vote car il ne répond pas au contexte de la question.
angryITguy
411

Je sais que c'est un ancien poste, mais j'avais déjà eu des problèmes avec lui auparavant. Trouvé une solution qui était de le faire dans la onBackStackChanged()fonction d'écoute

  @Override
    public void onBackPressed() {
        super.onBackPressed();

         Fragment f = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);
      if(f instanceof CustomFragmentClass) 
        // do something with f
        ((CustomFragmentClass) f).doSomething();

    }

Cela a fonctionné pour moi car je ne voulais pas parcourir chaque fragment que je dois trouver un qui est visible. J'espère que ça aide quelqu'un d'autre aussi.

Sev
la source
13
Exactement ce que je cherchais en traitant onBackPressed () après la rotation de l'écran avec un tiroir de navigation. Merci d'être revenu pour partager cela.
ShortFuse
1
FindFragmentById ne parcourt-il pas tous les fragments en interne? :)
Andrew Senner
46
dans le cas où le .getFragmentManagertype de rapport est incompatible, comme dans mon cas, c'est parce que j'utilisais le android.support.app.v4.Fragment, auquel cas la bonne méthode à utiliser estgetSupportFragmentManager
Răzvan Barbu
3
ou vous pouvez utiliser findFragmentByTag()à la place de findFragmentById, si vous avez fourni une balise à fragmenter lors de son ajout àfragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
DeltaCap019
@AndrewSenner, il veut dire qu'il ne voulait pas le faire explicitement :)
Farid
161

Voici ma solution que je trouve pratique pour les scénarios à faible fragment

public Fragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    if(fragments != null){
        for(Fragment fragment : fragments){
            if(fragment != null && fragment.isVisible())
                return fragment;
        }
    }
    return null;
}
Matt Mombrea
la source
13
fragmentpeut être nul dans certains scénarios, comme lorsque vous ouvrez la pile arrière. Donc une meilleure utilisation if (fragment != null && fragment.isVisible()).
cprcrack
8
méthode incomplète car il est possible qu'il n'y ait pas qu'un seul fragment visible
letroll
Si aucun fragment n'est visible, fragmentManager.getFragments () renverra NULL, ce qui amènera NPE à dire "Tenter d'appeler la méthode d'interface 'java.util.Iterator java.util.List.iterator ()' sur une référence d'objet NULL". Par conséquent, la boucle for doit être entourée d'une simple vérification: if (fragments! = Null)
Pranav Mahajan
Que faire si plusieurs fragments sont visibles?
Shivaraj Patil
5
Techniquement, cela devrait être marqué comme une réponse basée sur la question. Le demandeur souhaite un fragment actuellement affiché, sans savoir de quel fragment il s'agit. D'autres réponses continuent de recevoir des fragments par tag
angryITguy
76

Chaque fois que vous montrez un fragment, vous devez le mettre en backstack:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setTransition(FragmentTransaction.TRANSIT_ENTER_MASK);       
ft.add(R.id.primaryLayout, fragment, tag);
ft.addToBackStack(tag);
ft.commit();        

Et puis, lorsque vous devez obtenir le fragment actuel, vous pouvez utiliser cette méthode:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Dmitry_L
la source
4
Je suis assez sûr que cette technique ne fonctionnera pas pour les fragments utilisés avec un ViewPager, car ils ne sont pas ajoutés par balise. Il suffit de jeter ça là-bas.
loeschg
3
Cela ne semble fonctionner que lorsque vous appelez addToBackStack(tag), mais que se passe-t-il si vous ne souhaitez pas ajouter le fragment à la pile arrière?
cprcrack
1
Cela ne fonctionne que si votre balise est identique au nom de la pile arrière, ce qui semble inhabituel.
Que se passe-t-il si vous avez ajouté 5 fragments dans la même transaction?
Kevin Lam
Il est peut-être agréable de dire que si vous appelez addToBackStack (null) pour un fragment où vous n'avez pas besoin de nom, la méthode getName () peut retourner null et vous obtenez un NPE. @ dpk, docu dit: Obtenez le nom qui a été fourni à FragmentTransaction.addToBackStack (String) lors de la création de cette entrée. Ajoutez également une vérification nulle si EntryCount est 0 et vous essayez de recevoir l'entrée supérieure.
JacksOnF1re
23

Ce que j'utilise pour trouver le fragment d'affichage actuel est dans le code ci-dessous. C'est simple et ça marche pour moi maintenant. Il s'exécute dans l'activité qui détient les fragments

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
tainy
la source
3
Vous devez vérifier pour être sûr de compter> 0 afin que get (count-1) ne lève pas une exception IndexOutofBoundsException
kehers
@tainy cela ne donnera pas le fragment qui a été remplacé mais pas ajouté au backstack. Si oui, puis-je l'obtenir en utilisant l'argument tag?
cafebabe1991
L'appel getFragments ne vous donnera pas les fragments dans l'ordre dans lequel ils ont été ajoutés après que vous ayez appelé popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) dessus, et ajouté d'autres fragments.
LEHO
si l'activité a plus d'un fragment visible, votre chemin est faux. Par exemple: ViewPager avec fragments. comme je le savais, getBackStackEntryCount () renvoie le nombre de transactions, pas le nombre de fragments
HungNM2
Vous devriez vérifier fragManager.getFragments().size()au lieu de getBackStackEntryCount()car ils ne sont pas nécessairement égaux (ce qui est mon cas). Sinon, vous pouvez obtenir un crash avec IndexOutOfBoundsException
RustamG
20

Façon Kotlin;

val currentFragment = supportFragmentManager.fragments.last()
Cafer Mert Ceyhan
la source
Fonctionne uniquement sur l'API 26 et plus
ibit
1
@ibit que voulez-vous dire avec des travaux sur l'API 26 et plus uniquement? J'ai essayé l'émulateur API 19 qui fonctionnait bien.
HendraWD
@HendraWD vous avez raison! Je faisais référence à la fonction dans la getFragments()fonction frameworks , qui est API 26 et plus.
ibit
2
prends soin de toi. Si avant vous n'avez pas de pile de fragments, cela peut provoquer une exception vide!
Jetwiz
Ça ne marche pas? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment ne peut pas être converti en Fragment
coolcool1994
13

La manière réactive :

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
localhost
la source
7
comment est-ce réactif? Vous utilisez un observable mais il n'émettra qu'une seule fois
Tim
6
Et c'est juste une exagération. Un simple forloop amélioré ferait de même, peut-être même plus rapidement.
Peterstev Uremgba
utiliser un flux réactif pour juste api de flux n'est pas si intelligent, en fait, comme ils ont dit que c'est une exagération, utilisez l'api Java8 à vapeur si vous voulez traiter la liste comme un flux et appliquer l'api de filtre
AndroidLover
13

Ma méthode est basée sur try / catch comme ceci:

MyFragment viewer = null;
    if(getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT) instanceOf MyFragment){
    viewer = (MyFragment) getFragmentManager().findFragmentByTag(MY_TAG_FRAGMENT);
}

Mais il peut y avoir une meilleure façon ...

Thordax
la source
1
Ma question est de savoir comment obtenir le fragment actuellement affiché, ce qui signifie qu'il pourrait y avoir beaucoup de fragments, je veux seulement obtenir l'instance de celui actuellement affiché, pourquoi utiliser (MyFragment) ?? Je veux dire que cela pourrait être n'importe quel affichage de fragment à l'écran ... et je veux obtenir celui actuellement affiché.
Leem.fin
MY_TAG_FRAGMENT est la balise du fragment que j'ai créé avant d'utiliser un remplacement, comme ceci: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
Thordax
Si j'ai plusieurs fragments, puis-je utiliser une balise pour tous les fragments lorsque j'appelle .replace (...)?
Leem.fin
Oui, pas de problème, utilisez ce code: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); et ça peut aller bien.
Thordax
1
Eh bien, je ne comprends vraiment pas votre point, je veux dire que j'ai besoin d'un moyen d'obtenir immédiatement l'instance de fragment actuellement affichée, pas de vérifier itérativement tous les fragments, puis de décider quel fragment est maintenant affiché à l'écran.
Leem.fin
11

Eh bien, cette question a suscité beaucoup de vues et d'attention, mais ne contenait toujours pas la solution la plus simple de mon côté - utiliser getFragments ().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Nativ
la source
1
Malheureusement, ce n'est pas toujours vrai, le getSupportFragmentManager().getFragments() vous donne une liste mais qui peut contenir des valeurs nulles, si le dernier fragment vient d'être extrait du backstack. Eq: Si vous vérifiez votre chemin à l'intérieur de la onBackStackChanged()méthode et que vous appelez popBackStack()quelque part, alors le mCurrentFragmentsera null.
Stumi
@Stumi Merci pour ces informations. Oui, cela ressemble à l'un des nombreux problèmes de cycle de vie étranges dans Android.
Nativ
9

Vous pouvez interroger quel fragment est chargé dans votre cadre de contenu Activités et récupérer la classe de fragment ou le fragment «nom simple» (sous forme de chaîne).

public String getCurrentFragment(){
     return activity.getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();
}

Usage:

Log.d(TAG, getCurrentFragment());

Les sorties:

D/MainActivity: FragOne
Mr L
la source
8

C'est un peu tard, mais pour tous ceux qui sont intéressés: si vous connaissez l'index du fragment souhaité dans FragmentManager, obtenez simplement une référence et vérifiez la fonction isMenuVisible ()! ici :

getSupportFragmentManager().getFragments().get(0).isMenuVisible()

Si c'est truevisible pour l'utilisateur et ainsi de suite!

MohammadReza
la source
1
Curieusement, c'était la seule solution répertoriée ici qui fonctionnait pour moi. En même temps, plusieurs fragments peuvent avoir isVisible() == true, getView() != null. De plus, dans mon code getBackStackEntryCountest toujours nul. Même si je n'utilise pas de menu, isMenuVisible()c'est jusqu'à présent le seul discriminant qui semble pointer de manière fiable vers le fragment actuellement «actif». ty
parvus
7

1)

ft.replace(R.id.content_frame, fragment, **tag**).commit();

2)

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);

3)

if (currentFragment.getTag().equals(**"Fragment_Main"**))
{
 //Do something
}
else
if (currentFragment.getTag().equals(**"Fragment_DM"**))
{
//Do something
}
Nam Ngo Thanh
la source
6

Si vous arrivez ici et que vous utilisez Kotlin:

var fragment = supportFragmentManager.findFragmentById(R.id.fragment_container)

R.id.fragment_containerest l' idendroit où le fragmentprésente sur leuractivity

Ou si vous voulez une meilleure solution:

supportFragmentManager.findFragmentById(R.id.content_main)?.let {
    // the fragment exists

    if (it is FooFragment) {
        // The presented fragment is FooFragment type
    }
}
pableiros
la source
5

Inspiré par la réponse de Tainy , voici mes deux cents. Peu modifié de la plupart des autres implémentations.

private Fragment getCurrentFragment() {
    FragmentManager fragmentManager = myActivity.getSupportFragmentManager();
    int stackCount = fragmentManager.getBackStackEntryCount();
    if( fragmentManager.getFragments() != null ) return fragmentManager.getFragments().get( stackCount > 0 ? stackCount-1 : stackCount );
    else return null;
}

Remplacez-le "myActivity"par «ceci» s'il s'agit de votre activité actuelle ou utilisez une référence à votre activité.

Nashe
la source
5

Il y a une méthode appelée findFragmentById()dans SupportFragmentManager. Je l'utilise dans le conteneur d'activités comme:

public Fragment currentFragment(){
    return getSupportFragmentManager().findFragmentById(R.id.activity_newsfeed_frame);
}

Voilà comment obtenir votre courant Fragment. Si vous avez des coutumes Fragmentet devez vérifier de quoi Fragmentil s'agit, j'utilise normalement instanceof:

if (currentFragment() instanceof MyFrag){
    // Do something here
}
Kevin Murvie
la source
5

Si vous utilisez AndroidX Navigation:

val currentFragment = findNavController(R.id.your_navhost).?currentDestination

Pour plus d'informations sur ce composant de navigation: https://developer.android.com/guide/navigation/navigation-getting-started

Cory Roy
la source
Cela ne compile pas
IgorGanapolsky
1
Il ne se compilerait que si vous aviez correctement configuré la navigation AndroidX et que vous appeliez en quelque sorte votre navHost your_navhost.
Cory Roy
4

C'est un moyen simple d'obtenir le fragment actuel.

getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
  @Override public void onBackStackChanged() {
    currentFragment = fragmentManager.findFragmentById(R.id.content);
    if (currentFragment !=  null && (currentFragment instanceof LoginScreenFragment)) {
      logout.setVisibility(View.GONE);
    } else {
      logout.setVisibility(View.VISIBLE);
    }
  }
});
lallu Sukendh
la source
4

La réponse de Sev fonctionne lorsque vous appuyez sur le bouton de retour ou que vous modifiez le backstack.

J'ai cependant fait quelque chose de légèrement différent. J'ai une configuration d'écouteur de changement de backstack sur un fragment de base et ses fragments dérivés et ce code est dans l'écouteur:

Fragment f = getActivity().getSupportFragmentManager().findFragmentById(R.id.container);

if (f.getClass().equals(getClass())) {
    // On back button, or popBackStack(),
    // the fragment that's becoming visible executes here,
    // but not the one being popped, or others on the back stack

    // So, for my case, I can change action bar bg color per fragment
}
MCLLC
la source
3

C'est du travail pour moi. J'espère que cela va aider quelqu'un.

FragmentManager fragmentManager = this.getSupportFragmentManager();  
        String tag = fragmentManager
                    .getBackStackEntryAt(
                    fragmentManager
                    .getBackStackEntryCount() - 1)
                    .getName();
              Log.d("This is your Top Fragment name: ", ""+tag);
Cüneyt
la source
3

Si vous obtenez l'instance actuelle de Fragment de l'activité parent, vous pouvez simplement

findFragmentByID(R.id.container);

Il s'agit en fait de l'instance actuelle de fragment qui est remplie sur la vue. J'ai eu le même problème. J'ai dû charger le même fragment deux fois en en gardant un sur le backstack.

La méthode suivante ne fonctionne pas. Il obtient juste un fragment qui a la balise. Ne perdez pas votre temps avec cette méthode. Je suis sûr qu'il a ses utilisations, mais pour obtenir la version la plus récente du même fragment n'en fait pas partie.

findFragmentByTag()
Yasin Yaqoobi
la source
3

Découvrez cette solution. Cela a fonctionné pour moi d'obtenir le fragment actuel.

if(getSupportFragmentManager().getBackStackEntryCount() > 0){
        android.support.v4.app.Fragment f = 
         getSupportFragmentManager().findFragmentById(R.id.fragment_container);
        if(f instanceof ProfileFragment){
            Log.d(TAG, "Profile Fragment");
        }else if(f instanceof SavedLocationsFragment){
            Log.d(TAG, "SavedLocations Fragment");
        }else if(f instanceof AddLocationFragment){
            Log.d(TAG, "Add Locations Fragment");
        }
Haroon khan
la source
2
final FragmentManager fm=this.getSupportFragmentManager();
final Fragment fragment=fm.findFragmentByTag("MY_FRAGMENT");

if(fragment != null && fragment.isVisible()){
      Log.i("TAG","my fragment is visible");
}
else{
      Log.i("TAG","my fragment is not visible");
}
kmarin
la source
Cela fonctionne avec Jetpack?
IgorGanapolsky
2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Eh bien, je suppose que c'est la réponse la plus simple à cette question. J'espère que ça aide.

Abhishek
la source
2

Voici une solution Kotlin:

if ( this.getSupportFragmentManager().getBackStackEntryCount()>0 ) {
    var fgmt = this.getSupportFragmentManager().fragments[this.getSupportFragmentManager().getBackStackEntryCount()-1]
    if( fgmt is FgmtClassName ) {
        (fgmt as FgmtClassName).doSth()
    }
}

Manière simplifiée:

with ( this.getSupportFragmentManager() ) {
    if ( getBackStackEntryCount()>0 ) {
        var fgmt = fragments[getBackStackEntryCount()-1]
        if ( fgmt is FgmtClassName ) {
            (fgmt as FgmtClassName).doSth()
        }
    }
}
anamkin
la source
2

Un moyen simple de le faire:

Fragment fr=getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String fragmentName = fr.getClass().getSimpleName();
Biplob Das
la source
1

Dans l'activité principale, la méthode onAttachFragment (Fragment fragment) est appelée lorsqu'un nouveau fragment est attaché à l'activité. Dans cette méthode, vous pouvez obtenir l'instance du fragment actuel. Cependant, la méthode onAttachFragment n'est pas appelée lorsqu'un fragment est extrait de la backstack, c'est-à-dire lorsque le bouton de retour est enfoncé pour placer le fragment supérieur au sommet de la pile. Je recherche toujours une méthode de rappel qui est déclenchée dans l'activité principale lorsqu'un fragment devient visible à l'intérieur de l'activité.

ufdeveloper
la source
si proche! :-)
Blundell
Nous utilisons la bibliothèque de navigation Jetpack
IgorGanapolsky
1

Dans le cas de fragments déroulants, lorsque votre instance d'utilisation de la classe ViewPager suppose mVeiwPager, vous pouvez appeler mViewPager.getCurrentItem () pour obtenir le numéro actuel du fragment int.

dans MainLayout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:orientation="vertical"
    tools:context="unidesign.photo360.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="false"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:expanded="false">

        <android.support.v7.widget.Toolbar
            android:id="@+id/main_activity_toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:popupTheme="@style/AppTheme.PopupOverlay"
            app:title="@string/app_name">

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>


    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    </android.support.v4.view.ViewPager>
    
</android.support.design.widget.CoordinatorLayout>

dans MainActivity.kt

class MainActivity : AppCompatActivity() {
    
        lateinit var mViewPager: ViewPager
        lateinit var pageAdapter: PageAdapter
        
//      ...
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            
            pageAdapter = PageAdapter(supportFragmentManager)
            mViewPager = findViewById(R.id.view_pager)
//          ...
            }
            
        override fun onResume() {
          super.onResume()
          var currentFragment = pageAdapter.getItem(mViewPager.currentItem)
//         ...
          }

Andrei Radchenko
la source
1

J'ai trouvé findFragmentByTagque ce n'était pas pratique. Si vous en avez String currentFragmentTagdans votre Activityou parent Fragment, vous devez l'enregistrer onSaveInstanceStateet le restaurer onCreate. Même si vous le faites, lors de la Activityrecréation, onAttachFragmentsera appelé avant onCreate, vous ne pouvez donc pas l'utiliser currentFragmentTagdans onAttachFragment(par exemple, mettre à jour certaines vues en fonction decurrentFragmentTag ), car il n'est peut-être pas encore restauré.

J'utilise le code suivant:

Fragment getCurrentFragment() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if(fragments.isEmpty()) {
        return null;
    }
    return fragments.get(fragments.size()-1);
}

Le document FragmentManagerindiquant que

L'ordre des fragments dans la liste est l'ordre dans lequel ils ont été ajoutés ou attachés.

Lorsque vous devez faire des choses en fonction du type de fragment actuel, utilisez simplement getCurrentFragment() instance of MyFragmentau lieu de currentFragmentTag.equals("my_fragment_tag").

Notez que getCurrentFragment()in onAttachFragmentn'obtiendra pas la pièce Fragmentjointe, mais la précédente attachée.

Jeffrey Chen
la source
1

J'ai dû le faire très récemment et aucune des réponses ici ne convenait vraiment à ce scénario.

Si vous êtes sûr qu'un seul fragment sera visible (plein écran), alors voulez vraiment trouver ce qui se trouve en haut du backstack. Par exemple, comme Kotlinpour Fragment:

import androidx.fragment.app.Fragment

fun Fragment.setVisibilityChangeListener(clazz: Class<out Fragment>, listener: (Boolean) -> Unit) {
    fragmentManager?.run {
        addOnBackStackChangedListener {
            val topFragmentTag = getBackStackEntryAt(backStackEntryCount - 1).name
            val topFragment = findFragmentByTag(topFragmentTag)
            listener(topFragment != null && topFragment::class.java == clazz)
        }
    }
}

Et utilisez-le comme:

class MyFragment: Fragment {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        setVisibilityChangeListener(this::class.java) { visible -> 
            // Do stuff
        }
    }
}
Mikel Pascual
la source
1

Vous pouvez le faire très facilement également avec une URL dans logcat qui vous redirigera vers le code source du code source du fragment actuel. Tout d'abord, vous devez ajouter un OnBackStackChangedListener dans l'activité hôte comme -

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

Et l' implémentation OnBackStackChangedListener est -

    public FragmentManager.OnBackStackChangedListener backStackListener = () -> {

    String simpleName = "";
    String stackName = getStackTopName().trim();

    if (Validator.isValid(stackName) && stackName.length() > 0) {

      simpleName = stackName.substring(Objects.requireNonNull(stackName).lastIndexOf('.') + 1).trim();

      List<Fragment >
       fragmentList = getChildFragmentManager().getFragments();
      Fragment myCurrentFragment;

      for (int i = 0; i < fragmentList.size(); i++) {
       myCurrentFragment= fragmentList.get(i);
       if (myCurrentFragment.getClass().getSimpleName().equals(simpleName)) {
        //Now you get the current displaying fragment assigned in myCurrentFragment.
        break;
       }
       myFragment = null;
      }
     }


     //The code below is for the source code redirectable logcat which would be optional for you.
     StackTraceElement stackTraceElement = new StackTraceElement(simpleName, "", simpleName + ".java", 50);
     String fileName = stackTraceElement.getFileName();
     if (fileName == null) fileName = "";
     final String info = "Current Fragment is:" + "(" + fileName + ":" +
     stackTraceElement.getLineNumber() + ")";
     Log.d("now", info + "\n\n");
    };

Et la méthode getStackTopName () est -

public String getStackTopName() {
    FragmentManager.BackStackEntry backEntry = null;
    FragmentManager fragmentManager = getChildFragmentManager();
    if (fragmentManager != null) {
        if (getChildFragmentManager().getBackStackEntryCount() > 0)
            backEntry = getChildFragmentManager().getBackStackEntryAt(
                    getChildFragmentManager().getBackStackEntryCount() - 1
            );
    }
    return backEntry != null ? backEntry.getName() : null;
}
Gk Mohammad Emon
la source