Obtener el objeto fragmento actual

175

En mi main.xmltengo

  <FrameLayout
        android:id="@+id/frameTitle"
        android:padding="5dp"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:background="@drawable/title_bg">
            <fragment
              android:name="com.fragment.TitleFragment"
              android:id="@+id/fragmentTag"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content" />

  </FrameLayout>

Y estoy configurando un fragmento de objeto como este

FragmentManager fragmentManager = activity.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
Fragment newFragment = new FragmentType1();
fragmentTransaction.replace(R.id.frameTitle, casinodetailFragment, "fragmentTag");

// fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

Está configurando diferentes tipos de objetos Fragment ( FragmentType2,FragmentType3,...) en diferentes momentos. Ahora en algún momento necesito identificar qué objeto está actualmente allí.

En resumen , necesito hacer algo como esto:

Fragment currentFragment = //what is the way to get current fragment object in FrameLayout R.id.frameTitle

Probé lo siguiente

TitleFragment titleFragmentById = (TitleFragment) fragmentManager.findFragmentById(R.id.frameTitle);

y

    TitleFragment titleFragmentByTag = (TitleFragment) fragmentManager.findFragmentByTag("fragmentTag");

Pero ambos objetos (titleFragmentById y titleFragmentByTag) sonnull
¿Me perdí algo?
Estoy usando Compatibility Package, r3y desarrollando para API level 7.

findFragmentById()y findFragmentByTag()funcionará si hemos establecido un fragmento usando fragmentTransaction.replaceo fragmentTransaction.add, pero funcionará return nullsi hemos establecido el objeto en xml (como lo que hice en mi main.xml). Creo que me falta algo en mis archivos XML.

Labeeb Panampullan
fuente
Relacionado - stackoverflow.com/a/21104084/80428
Jay Wick
¿La respuesta @CommonsWare te ayuda, porque sigo siendo nulo?
IntoTheDeep

Respuestas:

253

Ahora en algún momento necesito identificar qué objeto está actualmente allí

Llamar findFragmentById()en FragmentManagery determinar qué fragmento se encuentra en su R.id.frameTitleenvase.

CommonsWare
fuente
1
Gracias por su respuesta. Funcionará si hemos establecido un fragmento usando fragmentTransaction.replace o fragmentTransaction.addpero no lo conseguiremos si lo hemos establecido en xml. Ver mi edición 2
Labeeb Panampullan
9
@Labeeb P: No puede modificar fragmentos declarados en los recursos de diseño.
CommonsWare
La creación de una clase para contener la pestaña / fragmento actualmente visible también funcionará, solo lo intenté. Espero que no haya fallas.
Skynet
@CommonsWare findFragmentByTagdevuelve nulo en caso de ActionBarpestañas. En mi Activityque se extiende, ActionBarActivityprimero agrego pestañas ActionBary luego lo encuentro.
Muhammad Babar
1
@MuhammadBabar: Puede probar executePendingTransactions()el FragmentManagerdespués de llamar commit()a la transacción, aunque no he probado esto. O puede usar setContentView()para usar un archivo de diseño con una <fragment>etiqueta. Cualquiera de los dos ocurre sincrónicamente, por lo que el fragmento existirá dentro de la onCreate()propia llamada donde usó executePendingTransaction()o setContentView(). De lo contrario, un ordinario FragmentTransactionse procesa de forma asíncrona, y ni siquiera habrá comenzado para cuando onCreate()termine el tiempo .
CommonsWare
110

Prueba esto,

Fragment currentFragment = getActivity().getFragmentManager().findFragmentById(R.id.fragment_container);

esto le dará el fragmento actual, luego puede compararlo con la clase de fragmento y hacer sus cosas.

    if (currentFragment instanceof NameOfYourFragmentClass) {
     Log.v(TAG, "find the current fragment");
  }
Martillo
fuente
¿Dónde poner esta línea?
Anand Savjani
9
A veces tiene que usar getSupportFragmentManager()en su lugar, y quedará nulo sin la supportparte
Muz
Elimine las citas de "NOMBRE DE SU CLASE DE FRAGMENTO".
Alan Nelson
37

Creo que puede usar el evento onAttachFragment puede ser útil para detectar qué fragmento está activo.

@Override
public void onAttachFragment(Fragment fragment) {
    // TODO Auto-generated method stub
    super.onAttachFragment(fragment);

    Toast.makeText(getApplicationContext(), String.valueOf(fragment.getId()), Toast.LENGTH_SHORT).show();

}
Hede Hodo
fuente
3
puedo obtener qué fragmento estoy adjunto. Mi deseo es cuando cambio la orientación, entonces necesito mostrar la misma vista, no otra vista, así que cómo hacerlo.
Androi Developer
77
Esto no funciona porque no actualiza el fragmento activo cuando regresa.
Justin
1
@Justin, así que solo necesitamos usar onDetach también con una lista de
referencia débil
12

Creo que deberías hacer:

Fragment currentFragment = fragmentManager.findFragmentByTag("fragmentTag");

La razón es porque configura la etiqueta "fragmentTag" en el último fragmento que ha agregado (cuando llamó a replace).

Niqo
fuente
Gracias lo he corregido. Es un error tipográfico al escribir esta pregunta. Funcionará si hemos establecido un fragmento usando fragmentTransaction.replace o fragmentTransaction.addpero no lo conseguiremos si lo hemos establecido en xml. Vea mi edición 2
Labeeb Panampullan
Muchas gracias! Resuelto mi problema!
Jonas Gröger
2
¿No significa esta solución que tienes que poner la misma etiqueta para varios fragmentos? de lo contrario, ¿cómo saber si fragmentTages la etiqueta para el fragmento actual?
Thupten
12

Puede obtener la lista de los fragmentos y buscar el último.

    FragmentManager fm = getSupportFragmentManager();
    List<Fragment> fragments = fm.getFragments();
    Fragment lastFragment = fragments.get(fragments.size() - 1);

Pero a veces (cuando navega hacia atrás) el tamaño de la lista sigue siendo el mismo, pero algunos de los últimos elementos son nulos. Entonces, en la lista, iteré hasta el último fragmento no nulo y lo usé.

    FragmentManager fm = getSupportFragmentManager();
    if (fm != null) {
        List<Fragment> fragments = fm.getFragments();
        if (fragments != null) {
            for(int i = fragments.size() - 1; i >= 0; i--){
                Fragment fragment = fragments.get(i);
                if(fragment != null) {
                    // found the current fragment

                    // if you want to check for specific fragment class
                    if(fragment instanceof YourFragmentClass) {
                        // do something
                    }
                    break;
                }
            }
        }
    }
eluleci
fuente
3
No uses el getFragments()método. Está marcado con @hidey no se suponía que debía incluirse con el archivo jar de la biblioteca de soporte. No debe considerarse como parte de la API exportada.
James Wald
Je, entonces deberían haber creado un método que te permita hacer exactamente lo que getFragments()hace, porque lo necesitas con bastante frecuencia. Creo que ahora también está disponible públicamente.
EpicPandaForce
10

Esta es la solución más simple y funciona para mí.

1.) agregas tu fragmento

ft.replace(R.id.container_layout, fragment_name, "fragment_tag").commit();

2.)

FragmentManager fragmentManager = getSupportFragmentManager();

Fragment currentFragment = fragmentManager.findFragmentById(R.id.container_layout);

if(currentFragment.getTag().equals("fragment_tag"))

{

 //Do something

}

else

{

//Do something

}
Gau
fuente
9

Puede que sea tarde, pero espero que ayude a alguien más, también @CommonsWare ha publicado la respuesta correcta.

FragmentManager fm = getSupportFragmentManager();
Fragment fragment_byID = fm.findFragmentById(R.id.fragment_id);
//OR
Fragment fragment_byTag = fm.findFragmentByTag("fragment_tag");
Ahmad Ali Nasir
fuente
9
Esto no le permite obtener el fragmento activo, ya que no necesariamente conoce la identificación o etiqueta.
Justin
7

Quizás la forma más simple es:

public MyFragment getVisibleFragment(){
    FragmentManager fragmentManager = MainActivity.this.getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();
    for(Fragment fragment : fragments){
        if(fragment != null && fragment.getUserVisibleHint())
            return (MyFragment)fragment;
    }
    return null;
}

Funciono para mi

madx
fuente
6

Puede crear un campo en su clase de actividad principal:

public class MainActivity extends AppCompatActivity {

    public Fragment fr;

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

}

Y luego dentro de cada clase de fragmento:

public class SomeFragment extends Fragment {

@Override
    public View onCreateView(LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        ((MainActivity) getActivity()).fr = this;
}

Su campo 'fr' es un fragmento actual Objeto

También funciona con popBackStack ()

buxik
fuente
4

Sé que ha pasado un tiempo, pero lo haré aquí en caso de que ayude a alguien.

La respuesta correcta con diferencia es (y la seleccionada) la de CommonsWare. Estaba teniendo el mismo problema que el publicado, el siguiente

MyFragmentClass fragmentList = 
            (MyFragmentClass) getSupportFragmentManager().findFragmentById(R.id.fragementID);

siguió volviendo nulo. Mi error fue realmente tonto, en mi archivo xml:

<fragment
    android:tag="@+id/fragementID"
    android:name="com.sf.lidgit_android.content.MyFragmentClass"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
/>

El error fue que tenía android: tag INSTEAD OF android: id .

Chayemor
fuente
2

La respuesta de @Hammer funcionó para mí, estoy usando para controlar un botón de acción flotante

final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            android.app.Fragment currentFragment = getFragmentManager().findFragmentById(R.id.content_frame);
            Log.d("VIE",String.valueOf(currentFragment));
            if (currentFragment instanceof PerfilFragment) {
                PerfilEdit(view, fab);
            }
        }
});
Thiago Melo
fuente
2

Si se está extendiendo desde AbstractActivity, podría usar el método getFragments ():

for (Fragment f : getFragments()) {
    if (f instanceof YourClass) {
        // do stuff here
    }
}
Marco Aurélio Alves Puton
fuente
1

Si está definiendo el fragmento en el diseño XML de la actividad, Activityasegúrese de llamar setContentView()antes de llamar findFragmentById().

IvancityM
fuente
1

Si está utilizando BackStack ... y SOLO si está utilizando Back stack, intente esto:

rivate Fragment returnToPreviousFragment() {

    FragmentManager fm = getSupportFragmentManager();

    Fragment topFrag = null;

    int idx = fm.getBackStackEntryCount();
    if (idx > 1) {
        BackStackEntry entry = fm.getBackStackEntryAt(idx - 2);
        topFrag = fm.findFragmentByTag(entry.getName());
    }

    fm.popBackStack();

    return topFrag;
}
James Barwick
fuente
0

Esto le dará el nombre de la clase de fragmento actual ->

String fr_name = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Biplob Das
fuente
0
  1. Haga una comprobación (qué fragmento en el contenedor de actividad) en el método onStart;

    @Override
    protected void onStart() {
    super.onStart();
    Fragment fragmentCurrent = getSupportFragmentManager.findFragmentById(R.id.constraintLayout___activity_main___container);
    }
  2. Algunos chequean:

    if (fragmentCurrent instanceof MenuFragment) 
Владислав Шестернин
fuente