¿Cómo obtengo el fragmento que se muestra actualmente?

444

Estoy jugando con fragmentos en Android.

Sé que puedo cambiar un fragmento usando el siguiente código:

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();

Mi pregunta es, en un archivo Java, ¿cómo puedo obtener la instancia de Fragment que se muestra actualmente?

Leem.fin
fuente
Relacionado - stackoverflow.com/a/21104084/80428
Jay Wick
1
Posible duplicado de Obtener el objeto fragmento actual
Sruit A.Suk

Respuestas:

453

Cuando agrega el fragmento en su transacción, debe usar una etiqueta.

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

... y luego si quieres comprobar si el fragmento es visible:

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

Ver también http://developer.android.com/reference/android/app/Fragment.html

ramdroid
fuente
74
Bien, pero necesito una forma de obtener de inmediato la instancia de Fragmento que se muestra actualmente, no verificar de forma iterativa todos los fragmentos y luego decidir qué fragmento se muestra ahora en la pantalla. Creo que su respuesta necesita mi código para verificar iterativamente cada uno de mis fragmentos, y encontrar el visible ...
Leem.fin
33
Sí, pero podría haber más de un fragmento visible a la vez. Así que no hay nada como el "único fragmento activo" ....
ramdroid
66
De acuerdo, incluso si se muestran varios fragmentos, todavía necesito una forma de obtenerlos ... y una forma que sea mejor que verificar iterativamente cada uno de mis fragmentos. Me preocupa "conseguirlos", un método como getDisplayedFragment (), pero no estoy seguro de si existe tal método en Android
Leem.fin
2
No sé por qué esto es un problema para usted ... Por lo general, solo tiene unos pocos fragmentos en una actividad y realmente no debería ser un problema verificarlos si son visibles o no.
ramdroid
12
¿Por qué todos votan esta respuesta? Claro, es un buen código pero no responde la pregunta para obtener un fragmento específico por etiqueta. PERO Asker quiere el fragmento que se muestra actualmente, lo que significa que no sabe qué fragmento se muestra. Sí, puede haber varios fragmentos, pero al leer la pregunta se infiere que solo se muestra 1 fragmento en la interfaz de usuario ... Lo siento, tuve que votar negativamente porque no responde el contexto de la pregunta.
angryITguy
410

Sé que es una publicación antigua, pero también tuve problemas con ella anteriormente. Encontré una solución que era hacer esto en la onBackStackChanged()función de escucha

  @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();

    }

Esto funcionó para mí, ya que no quería recorrer cada fragmento que tengo para encontrar uno que sea visible. Espero que ayude a alguien más también.

Sev
fuente
13
Exactamente lo que estaba buscando al tratar con onBackPressed () después de la rotación de la pantalla con un cajón de navegación. Gracias por volver a compartir esto.
ShortFuse
1
¿FindFragmentById no recorre todos los fragmentos internamente? :)
Andrew Senner
46
en caso de .getFragmentManagerinformes de tipo incompatible, como lo hizo en mi caso, es porque estaba usando el android.support.app.v4.Fragment, en cuyo caso el método correcto para usar esgetSupportFragmentManager
Răzvan Barbu
3
o puede usar findFragmentByTag()en lugar de findFragmentById, si ha proporcionado una etiqueta para fragmentar al agregarla afragmentManager.beginTransaction() .add(containerID, frag, fragmentTag) .addToBackStack(fragmentTag) .commit();
DeltaCap019
@ AndrewSenner, quiere decir que no quería hacerlo explícitamente :)
Farid
161

Aquí está mi solución, que encuentro útil para escenarios de bajo fragmento

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
fuente
13
fragmentpuede ser nulo en ciertos escenarios, como cuando hace estallar la pila posterior. Así que mejor uso if (fragment != null && fragment.isVisible()).
cprcrack
8
método incompleto porque es posible que no haya un solo fragmento visible
letroll
Si no hay ningún fragmento visible, fragmentManager.getFragments () devolverá NULL, lo que llevará a NPE a decir "Intento de invocar el método de interfaz 'java.util.Iterator java.util.List.iterator ()' en una referencia de objeto NULL". Por lo tanto, el bucle for debe estar rodeado por una simple verificación: if (fragments! = Null)
Pranav Mahajan
¿Qué pasa si hay más de un fragmento visible?
Shivaraj Patil
55
Técnicamente, esto debe marcarse como respuesta en función de la pregunta. El autor de la pregunta quiere que se muestre el fragmento actual, sin saber qué fragmento es. Otras respuestas siguen obteniendo fragmentos por etiqueta
angryITguy
76

Cada vez que muestres un fragmento debes poner la etiqueta en la pila:

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

Y luego, cuando necesite obtener un fragmento actual, puede usar este método:

public BaseFragment getActiveFragment() {
    if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
        return null;
    }
    String tag = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1).getName();
    return (BaseFragment) getSupportFragmentManager().findFragmentByTag(tag);
}
Dmitry_L
fuente
44
Estoy bastante seguro de que esta técnica no funcionará para los Fragmentos utilizados con un ViewPager, ya que no se agregan por etiqueta. Solo tirando eso por ahí.
loeschg
3
Esto solo parece funcionar cuando llamas addToBackStack(tag), pero ¿qué pasa si no quieres agregar el fragmento a la pila posterior?
cprcrack
1
Esto solo funciona si su etiqueta es la misma que el nombre de la pila posterior, lo que parece inusual.
¿Qué sucede si agregas 5 fragmentos en la misma transacción?
Kevin Lam
Quizás sea bueno decir que si llama a addToBackStack (nulo) para algún Fragmento donde no necesita un nombre, el método getName () puede devolver nulo y obtendrá un NPE. @ dpk, docu dice: Obtenga el nombre que se proporcionó a FragmentTransaction.addToBackStack (String) al crear esta entrada. Además, agregue una comprobación nula si EntryCount es 0 e intenta recibir la entrada superior.
JacksOnF1re
23

Lo que estoy usando para encontrar el fragmento de visualización actual se encuentra en el siguiente código. Es simple y funciona para mí por ahora. Se ejecuta en la actividad que contiene los fragmentos.

    FragmentManager fragManager = this.getSupportFragmentManager();
    int count = this.getSupportFragmentManager().getBackStackEntryCount();
    Fragment frag = fragManager.getFragments().get(count>0?count-1:count);
tainy
fuente
3
Debe verificar para asegurarse de contar> 0 para que get (cuenta-1) no arroje una excepción IndexOutofBoundsException
kehers
@tainy esto no dará el fragmento que fue reemplazado pero no agregado al backstack. ¿Correcto? En caso afirmativo, ¿puedo obtenerlo usando el argumento de etiqueta?
cafebabe1991
La llamada getFragments no le dará a los fragmentos el orden en que se agregaron después de llamar a popBackStack (null, FragmentManager.POP_BACK_STACK_INCLUSIVE) y agregará más fragmentos.
LEHO
Si la actividad tiene más de un Fragmento visible, su camino es incorrecto. Por ejemplo: ViewPager con Fragmentos. como sabía getBackStackEntryCount () devuelve el número de Transacción, no el número de fragmento
HungNM2
Debe verificar en fragManager.getFragments().size()lugar de, getBackStackEntryCount()ya que no son necesariamente iguales (que es mi caso). De lo contrario, puede bloquearse con IndexOutOfBoundsException
RustamG el
19

Camino de Kotlin;

val currentFragment = supportFragmentManager.fragments.last()
Cafer Mert Ceyhan
fuente
Funciona solo en API 26 y superiores
ibit
1
@ibit, ¿a qué te refieres con trabajos en API 26 y superiores solamente? Intenté en el emulador API 19 funcionando bien.
HendraWD
@HendraWD tienes razón! Me refería a la función en la getFragments()función frameworks , que es API 26 y superior.
ibit
2
Cuídate. Si antes no tienes ninguna pila de fragmentos, ¡puede causar una excepción vacía!
Jetwiz
Esto no funciona? java.lang.ClassCastException: androidx.navigation.fragment.NavHostFragment no se puede enviar a Fragment
coolcool1994
13

La forma reactiva :

Observable.from(getSupportFragmentManager().getFragments())
    .filter(fragment -> fragment.isVisible())
    .subscribe(fragment1 -> {
        // Do something with it
    }, throwable1 -> {
        // 
    });
localhost
fuente
77
¿Cómo es eso reactivo? Utiliza un observable pero solo emitirá una vez
Tim
66
Y es solo una exageración. Un forloop mejorado simple haría lo mismo, tal vez incluso más rápido.
Peterstev Uremgba
el uso de la transmisión reactiva solo para la API de transmisión no es tan inteligente, de hecho, como dijeron, es una exageración usar la API Java8 de steam si quieres tratar la lista como una transmisión y aplicar la API de filtro
AndroidLover
13

Mi método se basa en try / catch de esta manera:

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

Pero puede haber una mejor manera ...

Thordax
fuente
1
Mi pregunta es cómo obtener el fragmento que se muestra actualmente, lo que significa que podría haber muchos fragmentos, solo quiero obtener la instancia del que se muestra actualmente, ¿por qué usar (MyFragment)? Quiero decir que podría ser cualquier visualización de Fragment en la pantalla ... y quiero obtener la que se muestra actualmente.
Leem.fin
MY_TAG_FRAGMENT es la etiqueta del fragmento que creé antes de usar un reemplazo, como este: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT);
Thordax
Si tengo varios fragmentos, ¿puedo usar una etiqueta para todos los fragmentos cuando llame a .replace (...)?
Leem.fin
Sí, no hay problema, use este código: fragmentTransaction.replace (R.id.FL_MyFragment, MyFragment, MY_TAG_FRAGMENT); y puede ir bien
Thordax
1
Bueno, realmente no entiendo su punto, quiero decir que necesito una forma de obtener inmediatamente la instancia de Fragmento que se muestra actualmente, no verificar de forma iterativa todos los fragmentos y luego decidir qué fragmento se muestra ahora en la pantalla.
Leem.fin
11

Bueno, esta pregunta obtuvo muchas opiniones y atención, pero aún no contenía la solución más fácil de mi parte: usar getFragments ().

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);
Nativ
fuente
1
Desafortunadamente, esto no siempre es cierto, getSupportFragmentManager().getFragments() le devuelve una lista, pero puede contener valores nulos, si el último fragmento acaba de salir de la pila. Eq: si verifica con su método interno onBackStackChanged()y llama a popBackStack()algún lugar, entonces mCurrentFragmentserá null.
Stumi
@Stumi Gracias por esta información. Sí, suena como uno de los muchos problemas extraños del ciclo de vida en Android.
Nativ
9

Puede consultar qué fragmento se carga en su marco de contenido de Actividades y recuperar la clase de fragmento o el fragmento 'nombre simple' (como una cadena).

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

Uso:

Log.d(TAG, getCurrentFragment());

Salidas:

D/MainActivity: FragOne
Señor l
fuente
8

Es un poco tarde, pero para cualquiera que esté interesado: si conoce el índice del fragmento que desea en FragmentManager, solo obtenga una referencia y verifique la función isMenuVisible (). aquí :

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

Si es truevisible para el usuario, etc.

MohammadReza
fuente
1
Por extraño que parezca, esta fue la única solución enumerada aquí que funcionó para mí. Al mismo tiempo, varios fragmentos pueden tener isVisible() == true, getView() != null. Además, en mi código getBackStackEntryCountsiempre es cero. Aunque no uso los menús, isMenuVisible()hasta ahora es el único discriminante que parece apuntar de manera confiable al fragmento 'activo' actual. 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
fuente
6

Si llegas aquí y estás usando Kotlin:

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

R.id.fragment_containeres el lugar iddonde fragmentse presenta en suactivity

O si quieres una mejor solución:

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

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

Inspirado por la respuesta de Tainy , aquí están mis dos centavos. Poco modificado de la mayoría de las otras implementaciones.

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;
}

Reemplace "myActivity"con "esto" si es su actividad actual o use una referencia a su actividad.

Nashe
fuente
5

Hay un método llamado findFragmentById()en SupportFragmentManager. Lo uso en el contenedor de actividades como:

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

Así es como obtener su actual Fragment. Si tiene una costumbre Fragmenty necesita verificar qué Fragmentes, normalmente uso instanceof:

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

Si está utilizando el AndroidX Navigation:

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

Para obtener más información sobre este componente de navegación: https://developer.android.com/guide/navigation/navigation-getting-started

Cory Roy
fuente
Esto no compila
IgorGanapolsky
1
Solo se compilaría si configuró correctamente la navegación de AndroidX y de alguna manera llamó a su navHost your_navhost.
Cory Roy
4

Esta es una forma sencilla de obtener el fragmento actual.

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
fuente
4

La respuesta de Sev funciona cuando presionas el botón Atrás o cambias la pila.

Sin embargo, hice algo un poco diferente. Tengo una configuración de escucha de cambio de backstack en un Fragmento base y sus fragmentos derivados y este código está en la escucha:

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
fuente
3

Esto es trabajo para mi. Espero que esto ayude a alguien.

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

Si obtiene la instancia actual de Fragmento de la actividad principal, puede simplemente

findFragmentByID(R.id.container);

Esto realmente es la instancia actual de fragmento que se rellena en la vista. Tuve el mismo problema. Tuve que cargar el mismo fragmento dos veces manteniendo uno en el backstack.

El siguiente método no funciona. Simplemente obtiene un Fragment que tiene la etiqueta. No pierdas tu tiempo con este método. Estoy seguro de que tiene sus usos, pero obtener la versión más reciente del mismo Fragmento no es uno de ellos.

findFragmentByTag()
Yasin Yaqoobi
fuente
3

Echa un vistazo a esta solución. Me funcionó para obtener el Fragmento actual.

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
fuente
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
fuente
Esto funciona con Jetpack?
IgorGanapolsky
2
getSupportFragmentManager().findFragmentById(R.id.content_frame).getClass().getSimpleName();

Bueno, supongo que esta es la respuesta más directa a esta pregunta. Espero que esto ayude.

Abhishek
fuente
2

Aquí hay una solución de Kotlin:

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

Forma simplificada:

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

Manera fácil de hacer eso:

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

En la actividad principal, se llama al método onAttachFragment (Fragment fragment) cuando se adjunta un nuevo fragmento a la actividad. En este método, puede obtener la instancia del fragmento actual. Sin embargo, no se llama al método onAttachFragment cuando se saca un fragmento de la pila, es decir, cuando se presiona el botón Atrás para colocar el fragmento superior en la parte superior de la pila. Todavía estoy buscando un método de devolución de llamada que se active en la actividad principal cuando un fragmento se hace visible dentro de la actividad.

ufdeveloper
fuente
tan cerca :-)
Blundell
Usamos la biblioteca Jetpack Navigation
IgorGanapolsky
1

En el caso de fragmentos desplazados, cuando use la instancia de la clase ViewPager, suponga que mVeiwPager, puede llamar a mViewPager.getCurrentItem () para obtener el número int del fragmento actual.

en 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>

en 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
fuente
1

Descubrí findFragmentByTagque no es tan conveniente. Si tiene String currentFragmentTagen su Activityo padre Fragment, necesita guardarlo onSaveInstanceStatey restaurarlo onCreate. Incluso si lo hace, cuando el Activityrecreada, onAttachFragmentserá llamado antes onCreate, por lo que no se puede utilizar currentFragmentTagen onAttachFragment(por ejemplo. Actualizar algunos puntos de vista basados en currentFragmentTag), ya que de fuerza aún no restaurado.

Yo uso el siguiente código:

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

El documento de FragmentManagerestado que

El orden de los fragmentos en la lista es el orden en que se agregaron o adjuntaron.

Cuando necesite hacer cosas basadas en el tipo de fragmento actual, simplemente use en getCurrentFragment() instance of MyFragmentlugar de currentFragmentTag.equals("my_fragment_tag").

Tenga getCurrentFragment()en cuenta que onAttachFragmentno obtendrá el Fragmentadjunto, sino el adjunto anterior.

Jeffrey Chen
fuente
1

Tuve que hacer esto muy recientemente y ninguna de las respuestas aquí realmente se ajustaba a este escenario.

Si está seguro de que solo un fragmento estará visible (pantalla completa), entonces realmente desea encontrar lo que está en la parte superior de la pila. Por ejemplo, como Kotlinpara 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)
        }
    }
}

Y úsalo como:

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

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

Puede hacerlo muy fácilmente también con una URL en logcat que lo redirigirá al código fuente del código fuente del fragmento actual. Primero, debe agregar un OnBackStackChangedListener en la actividad del host como -

activity.getChildFragmentManager().addOnBackStackChangedListener(backStackListener);

Y la implementación de OnBackStackChangedListener es:

    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");
    };

Y el método getStackTopName () es -

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
fuente